Localization Release QA avatar

Localization Release QA

Pricing

$0.15 / completed report

Go to Apify Store
Localization Release QA

Localization Release QA

Check supplied locale JSON for missing keys, empty text, type changes, interpolation errors and declared i18next plural categories. Download translator CSV, JSON and HTML.

Pricing

$0.15 / completed report

Rating

0.0

(0)

Developer

Gilad Ronen

Gilad Ronen

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

What does Localization Release QA do?

Catch structural defects in a translation delivery before a release. Supply a base locale and target locale JSON resources, choose a syntax policy, and receive a translator review queue with exact paths, evidence, and suggested human actions. The Actor runs entirely on the supplied data; it does not fetch a website, upload strings to a translation service, or generate translations.

Why use Localization Release QA?

Use it after a translator returns a resource bundle, before merging localization changes, or as a release step in an Apify, n8n, or Make workflow. A structurally valid JSON file can still omit a key, rename an interpolation variable, or change an array into an object. This report makes those differences explicit.

How to use Localization Release QA

  1. Open the Input tab and paste your base resource and target locales.
  2. Choose plain or i18next-v4, then declare any plural families and exclusions.
  3. Run the Actor and review the summary before handing the issue CSV to your translator.

Use this input example:

{
"baseLocale": "en",
"base": {
"greeting": "Hello {{name}}",
"cart_one": "One item",
"cart_other": "{{count}} items"
},
"locales": [
{
"locale": "de",
"translations": {
"greeting": "Hallo {{vorname}}",
"cart_one": "Ein Artikel",
"cart_other": "{{count}} Artikel"
}
}
],
"syntax": "i18next-v4",
"pluralFamilies": ["/cart"]
}

This example reports one missing variable, name, and one extra variable, vorname. It does not require {{count}} in the singular string. For each run, download the full JSON report, translator CSV, or standalone HTML file from the output links.

Supply exactly one base object or baseJson string containing pasted JSON. For each target, supply exactly one translations object or translationsJson pasted string. Pasted text is checked for duplicate JSON member names, including escaped-equivalent names. Once another JSON parser has already discarded duplicate object keys, those lost duplicates cannot be recovered; use the text fields when duplicate detection matters.

Input checks and policies

  • Missing and extra keys: compared recursively. A wholly missing or extra subtree creates one finding at its root. Strings in present extra subtrees are also inspected for unsupported syntax.
  • Value kinds: strings, numbers, booleans, null, arrays, and objects remain distinct. Non-text leaves and empty containers receive review warnings. String identifiers such as 001 remain strings.
  • Empty text: empty or whitespace-only strings are errors by default. Set treatEmptyAsMissing to false to make them review warnings; they still appear in the report.
  • Interpolation: i18next-v4 supports simple {{name}}, data-model paths such as {{author.name}}, and unescaped {{- name}}. Variable names and the set of escape modes must match. Word order and repeated occurrences are not compared.
  • Plain mode: keys such as item_one have no plural meaning. Interpolation-like text creates an unsupported-syntax finding. Undeclared suffix keys also remain ordinary keys in i18next mode.
  • Exact ignores: ignorePaths contains at most 200 exact JSON Pointers. The named node and its descendants are excluded, and every ignored path must exist in at least one locale. There are no regular expressions or wildcard patterns. A literal * is simply a key character.

Paths use JSON Pointer rather than dot notation. /checkout.greeting is a literal dotted key, /checkout/greeting is a nested key, /items/0 is the first array element, and ~1 / ~0 escape slash / tilde characters in member names. Array-versus-object distinctions are retained in the evidence types. The empty pointer denotes the root.

Cardinal plural families

Declare exact family stems in pluralFamilies, for example /cart/items for keys items_one and items_other under cart. The base must contain an object parent and at least one recognized category key. At most 500 families are allowed. A declared family or category cannot be ignored.

The Actor uses each locale's Intl.PluralRules cardinal categories. Arabic and Japanese therefore do not need the same suffix keys as English. It checks required categories in the base as well as targets. A _zero special form is allowed even when not required by that locale. Extra nonzero categories receive review warnings. Plural category values must be strings.

For placeholder comparison, a target category uses the same source category when present, otherwise source _other. This is an explicit structural reference policy, not a claim that every grammatical form needs identical wording. Legitimate language-specific placeholder differences need human review. The application still needs to pass the i18next runtime count option; the Actor cannot inspect calls to t() and does not require the string itself to contain a count placeholder. The report records Node and ICU versions and the resolved category lists.

Unsupported syntax and scope

ICU messages, sprintf placeholders, i18next nesting, format expressions, ordinal/interval plurals, custom delimiters, runtime interpolation settings, and framework plugins are not parsed. Common signatures and unresolved braces produce explicit findings. Detection is conservative and may flag literal braces or delimiter-like prose. Arbitrary custom syntax cannot be discovered reliably from text alone: declare known features in unsupportedFeatures using icu, sprintf, nesting, custom-delimiters, formatting, ordinal, or interval. Every declaration forces review. No report with an unsupported finding receives passed status.

The supported simple variable grammar uses Unicode letters/numbers, underscore, and dollar sign in dot-separated segments. Other variable expressions are flagged. This Actor does not assess translation meaning, fluency, terminology, language identity, codebase unused keys, runtime fallback behavior, markup correctness, visual layout, accessibility, or regulatory compliance. It performs no automatic edits.

Output and automation

The dataset contains exactly one complete report with summary, policy, localeRules, and rows. Each issue has a stable ID, severity, code, locale, JSON Pointer, source reference, evidence types, evidence excerpts, reason, and human action. Stable IDs depend on engine version, locale, path, issue code, and variable identity; unrelated new findings do not renumber existing issues.

summary.status is failed when errors exist, review-required for warnings only, and passed when no findings remain within the configured scope. In a workflow, wait for run completion, read the first dataset item, and gate the release on your chosen status. A completed Actor run with failed QA status is still a successfully delivered report.

The OUTPUT JSON record mirrors the report. translator-issues.csv provides one issue per row with a UTF-8 BOM, quoted fields, and spreadsheet-formula neutralization. report.html is escaped, standalone, and script-free; use the download link and open the file locally. Evidence uses JSON-encoded text excerpts, capped at 600 UTF-16 code units plus an ellipsis; evidenceTruncated marks clipping. Containers show type and size. Full original values remain in your supplied input, which the Actor does not modify. Logs contain status counts rather than customer translation values.

A shortened issue example is:

{
"summary": { "status": "failed", "issues": 2, "errors": 2 },
"rows": [
{
"code": "INTERPOLATION_MISSING",
"locale": "de",
"path": "/greeting",
"reason": "Missing interpolation variable: name.",
"action": "Restore the exact source variable name, keeping its escape mode."
}
]
}
Output fieldHow to use it
summary.statusGate a release on your chosen acceptance policy.
rows[].idTrack the same finding across repeated deliveries.
rows[].locale, pathLocate the resource value needing attention.
rows[].referencePathFind the source form used for comparison.
rows[].baseEvidence, targetEvidenceReview preserved excerpts and types.
rows[].actionAssign a concrete review step to a translator or developer.

Limits, price, and recovery

A run accepts 2–20 locales including the base, 10,000 combined leaves, and translation depth 20. Empty objects/arrays count as leaves. The complete input, including pasted-text escaping and policy metadata, must be at most 2,000,000 UTF-8 bytes. This conservative whole-input limit is slightly tighter than measuring raw translation text alone. No sampling occurs. Reports must remain below 20,001 findings, 8 MB of JSON, and 9 MB per downloadable export. If an output would exceed a limit, split the locales or resource files; no partial report event is charged.

The listed price is $0.15 per completed report, including platform usage. Invalid input or insufficient run budget causes no report event. A completed audit containing errors is billable. Each new run is independently billable. Paid configuration supports only the report-completed event; positive startup, default dataset-item, or other events are rejected. Promotional prices below $0.15 are accepted.

The dataset JSON is the primary deliverable. If an export write is interrupted after publication and charging, the dataset remains available; resurrecting that same run regenerates downloads without a second report event. Recovery checks the input fingerprint and recomputes the supplied-data report to reject modified evidence, engine changes, or runtime changes. An interrupted charge after the dataset write is completed once on recovery. A charged run whose dataset item is missing is refused for inspection. Cloud storage and billing remain platform operations; this behavior does not promise an atomic multi-file transaction.

No external account, proxy, API key, browser session, or translation-service subscription is required. Keep unreleased translations in your own authorized Apify storage and apply your normal retention and sharing settings.

Tips and support

Save the same explicit policy in an Apify Task to reuse it after each translation delivery. Apify API access and integrations can connect the report to an existing workflow; the Actor itself does not watch files or maintain translation history. Split resource namespaces or locale groups when a bundle approaches the documented limits. Use the Actor’s Issues tab for reproducible bug reports using synthetic strings instead of confidential customer text.

The supported syntax follows the official i18next interpolation documentation and cardinal plural documentation, with the narrower parser boundaries described above.