mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 02:29:55 +02:00
feat(l10n): single-source localization pipeline
Add localization/ — one strings.json is the source of truth for every
user-facing string, and a Bun CLI generates the platform files:
loc migrate rebuild strings.json from existing platform files (one-time)
loc validate structural checks (plural `other`, arg refs, coverage)
loc generate emit .xcstrings (Apple) + per-language strings.xml (KMP)
Canonical `{name}` placeholders are converted to each platform's positional
printf tokens using declared arg types. Plurals use CLDR categories and emit
native forms: xcstrings plural variations and Compose <plurals> blocks.
Migration folds the KMP `transfer_file_count_one`/`_other` pair into a single
plural key, so `transferFileCountResource` now returns the plural resource and
callers resolve it with pluralStringResource.
This commit is contained in:
72
localization/schema.json
Normal file
72
localization/schema.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "VniDrop localization source",
|
||||
"type": "object",
|
||||
"required": ["sourceLanguage", "supportedLanguages", "strings"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"sourceLanguage": { "type": "string", "description": "Default/base language code, e.g. \"en\"." },
|
||||
"supportedLanguages": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"strings": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "$ref": "#/definitions/entry" }
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"entry": {
|
||||
"type": "object",
|
||||
"required": ["context"],
|
||||
"additionalProperties": false,
|
||||
"oneOf": [
|
||||
{ "required": ["translations"] },
|
||||
{ "required": ["plural"] },
|
||||
{ "not": { "anyOf": [{ "required": ["translations"] }, { "required": ["plural"] }] } }
|
||||
],
|
||||
"properties": {
|
||||
"context": { "type": "string" },
|
||||
"targets": {
|
||||
"type": "array",
|
||||
"items": { "enum": ["kmp", "apple"] },
|
||||
"uniqueItems": true
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["name", "type"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
|
||||
"type": { "enum": ["string", "int", "double"] }
|
||||
}
|
||||
}
|
||||
},
|
||||
"translations": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "type": "string" }
|
||||
},
|
||||
"plural": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"required": ["other"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"zero": { "type": "string" },
|
||||
"one": { "type": "string" },
|
||||
"two": { "type": "string" },
|
||||
"few": { "type": "string" },
|
||||
"many": { "type": "string" },
|
||||
"other": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user