Merge remote-tracking branch 'origin/main' into saas-update

# Conflicts:
#	engine/src/stirling/documents/pgvector_store.py
This commit is contained in:
James Brunton
2026-06-15 14:10:21 +01:00
78 changed files with 367 additions and 343 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ public class PropSync {
File folder = new File("C:\\Users\\systo\\git\\Stirling-PDF\\app\\core\\src\\main\\resources");
File[] files = folder.listFiles((dir, name) -> name.matches("messages_.*\\.properties"));
List<String> enLines = Files.readAllLines(Paths.get(folder + "\\messages_en_GB.properties"), StandardCharsets.UTF_8);
List<String> enLines = Files.readAllLines(Path.of(folder + "\\messages_en_GB.properties"), StandardCharsets.UTF_8);
Map<String, String> enProps = linesToProps(enLines);
for (File file : files) {
+2 -2
View File
@@ -19,9 +19,9 @@ public class RestartHelper {
Map<String, String> cli = parseArgs(args);
long pid = Long.parseLong(req(cli, "pid"));
Path appJar = Paths.get(req(cli, "app")).toAbsolutePath().normalize();
Path appJar = Path.of(req(cli, "app")).toAbsolutePath().normalize();
String javaBin = cli.getOrDefault("java", "java");
Path argsFile = cli.containsKey("argsFile") ? Paths.get(cli.get("argsFile")) : null;
Path argsFile = cli.containsKey("argsFile") ? Path.of(cli.get("argsFile")) : null;
long backoffMs = Long.parseLong(cli.getOrDefault("backoffMs", "1000"));
if (!Files.isRegularFile(appJar)) {
+57 -2
View File
@@ -10,6 +10,8 @@
# Inputs:
# STIRLING_JAR - path to a pre-built Stirling-PDF .jar (defaults to the
# :stirling-pdf:bootJar output)
# JAVA_BIN - override the Java executable used to launch the JAR
# (defaults to MIGRATION_TEST_JAVA, JAVA_HOME, then PATH)
# FIXTURE_DIR - override the fixture directory (rarely needed)
#
# Exits non-zero on any fixture failure and writes a summary to stderr.
@@ -19,6 +21,7 @@ set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
FIXTURE_DIR="${FIXTURE_DIR:-$REPO_ROOT/app/proprietary/src/test/resources/db-migration-fixtures}"
STIRLING_JAR="${STIRLING_JAR:-}"
JAVA_BIN="${JAVA_BIN:-${MIGRATION_TEST_JAVA:-}}"
ADMIN_USERNAME="${ADMIN_USERNAME:-admin}"
ADMIN_PASSWORD="${ADMIN_PASSWORD:-stirling}"
STARTUP_TIMEOUT_SEC="${STARTUP_TIMEOUT_SEC:-300}"
@@ -26,6 +29,52 @@ STARTUP_TIMEOUT_SEC="${STARTUP_TIMEOUT_SEC:-300}"
log() { printf '[migration-test] %s\n' "$*" >&2; }
fail() { printf '[migration-test][FAIL] %s\n' "$*" >&2; exit 1; }
java_major_version() {
local java_bin="$1"
"$java_bin" -XshowSettings:properties -version 2>&1 \
| awk -F'= ' '/java.specification.version =/ { print $2; exit }'
}
find_java() {
local candidate
if [[ -n "$JAVA_BIN" ]]; then
if [[ -x "$JAVA_BIN" ]]; then
candidate="$JAVA_BIN"
elif command -v "$JAVA_BIN" >/dev/null 2>&1; then
candidate=$(command -v "$JAVA_BIN")
else
fail "JAVA_BIN/MIGRATION_TEST_JAVA='$JAVA_BIN' is not executable or on PATH"
fi
elif [[ -n "${JAVA_HOME:-}" && -x "${JAVA_HOME}/bin/java" ]]; then
candidate="${JAVA_HOME}/bin/java"
else
local java_home_var
for java_home_var in JAVA_HOME_25_X64 JAVA_HOME_25_ARM64 JAVA_HOME_25_AARCH64; do
local java_home="${!java_home_var:-}"
if [[ -n "$java_home" && -x "$java_home/bin/java" ]]; then
candidate="$java_home/bin/java"
break
fi
done
if [[ -z "${candidate:-}" ]]; then
candidate=$(command -v java || true)
fi
fi
[[ -n "${candidate:-}" ]] || fail "No java executable found; install JDK 25 or set JAVA_BIN"
realpath "$candidate"
}
assert_supported_java() {
local java_bin="$1"
local major
major=$(java_major_version "$java_bin")
[[ -n "$major" ]] || fail "Could not determine Java version from '$java_bin'"
if (( major < 25 )); then
fail "Migration test requires JDK 25+ to run the built JAR, but '$java_bin' is Java $major. Set JAVA_HOME or JAVA_BIN to a JDK 25 installation."
fi
}
find_jar() {
local candidate
if [[ -n "$STIRLING_JAR" ]]; then
@@ -63,7 +112,9 @@ test_fixture() {
label=$(basename "$fixture_path" .mv.db)
log "=== $label ==="
local jar; jar=$(find_jar)
local jar
jar=$(find_jar)
local java_bin="$MIGRATION_JAVA_BIN"
local workdir; workdir=$(mktemp -d)
local configsdir="$workdir/configs"
mkdir -p "$configsdir"
@@ -74,6 +125,7 @@ test_fixture() {
local log_file="$workdir/app.log"
log " jar=$jar"
log " java=$java_bin ($("$java_bin" -version 2>&1 | head -n 1))"
log " workdir=$workdir"
log " port=$port"
@@ -86,7 +138,7 @@ test_fixture() {
# to cwd, and we want to make sure we hit the fixture's configs/ and not
# whatever happens to live at the runner's working directory.
pushd "$workdir" >/dev/null
java -Xmx1g -jar "$jar" \
"$java_bin" -Xmx1g -jar "$jar" \
"--server.port=$port" \
"--spring.datasource.url=jdbc:h2:file:./configs/stirling-pdf-DB-2.3.232;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE;MODE=PostgreSQL" \
"--spring.jpa.show-sql=false" \
@@ -169,6 +221,9 @@ test_fixture() {
main() {
[[ -d "$FIXTURE_DIR" ]] || fail "Fixture dir not found: $FIXTURE_DIR"
MIGRATION_JAVA_BIN=$(find_java)
assert_supported_java "$MIGRATION_JAVA_BIN"
local fixtures
mapfile -t fixtures < <(find "$FIXTURE_DIR" -maxdepth 1 -name '*.mv.db' | sort)
[[ ${#fixtures[@]} -gt 0 ]] || fail "No fixtures under $FIXTURE_DIR"
+40
View File
@@ -482,6 +482,46 @@ title = "Add Page Numbers"
Keys use dot notation internally (e.g., `addPageNumbers.selectText.1`).
### Pluralization Suffixes
Pluralized i18n keys use the i18next/Intl plural suffixes:
`_zero`, `_one`, `_two`, `_few`, `_many`, and `_other`.
Define the shared base key plus one entry for each plural category the language
needs. Always provide `_other`; i18next uses it as the fallback plural form.
Use `{{count}}` as the count placeholder, and call the base key from code with a
`count` value:
```toml
[common]
fileCount_one = "{{count}} file"
fileCount_other = "{{count}} files"
fileCount_zero = "No files"
```
Languages with more plural categories can add their required forms. For example,
Arabic-style plural rules distinguish `0`, `1`, `2`, small counts, large counts,
and the fallback form:
```toml
[common]
uploadCount_zero = "No files uploaded" # count = 0
uploadCount_one = "One file uploaded" # count = 1
uploadCount_two = "Two files uploaded" # count = 2
uploadCount_few = "{{count}} files uploaded" # count = 3-10
uploadCount_many = "{{count}} files uploaded" # count = 11-99
uploadCount_other = "{{count}} files uploaded" # count = 100, fractions, fallback
```
```ts
t("common.uploadCount", { count: files.length });
```
Do not translate the suffix names themselves. They are CLDR plural categories,
not English words. Add only the forms required by the target language, but keep
the plural key set aligned with `en-US` unless the target language needs
additional CLDR forms such as `_few` or `_many`.
## Key Features
### Placeholder Preservation