@ai-translate/apple 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thiago Peres
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # @ai-translate/apple
2
+
3
+ Native Apple localization resources for ai-translate. Works with SwiftUI, UIKit,
4
+ AppKit, Swift packages, and any application that loads Apple string resources.
5
+
6
+ ```bash
7
+ npm install --save-dev @ai-translate/apple @ai-translate/cli @ai-translate/fs-json @ai-translate/provider-openai
8
+ ```
9
+
10
+ Requires Node 20.19+. Resource translation runs on any supported operating
11
+ system; Xcode resource extraction and app compilation require Apple's tools.
12
+
13
+ ## Xcode string catalogs
14
+
15
+ ```ts
16
+ import { createAppleStringCatalog } from "@ai-translate/apple";
17
+
18
+ const native = createAppleStringCatalog({
19
+ id: "native",
20
+ rootDir: "Shared/Resources",
21
+ sourceLocale: "en",
22
+ // Optional globs relative to rootDir:
23
+ include: ["**/*.xcstrings"],
24
+ });
25
+ ```
26
+
27
+ Add this adapter to your configuration's `catalogs` array. Every `.xcstrings`
28
+ file is one document unit, named by its relative path without the extension;
29
+ every locale writes to the same physical file. The source language must match
30
+ `sourceLocale`. Discovery excludes common build/dependency directories.
31
+
32
+ Only string-unit values are translated. Source text falls back to the key when
33
+ there is no explicit source localization. Comments and variant context reach
34
+ the provider. Metadata, source content, unrelated locales, and nontranslatable
35
+ entries are preserved. Empty keys, `shouldTranslate: false`, and stale extracted
36
+ entries are skipped. String Catalog versions 1.0–1.3 are supported and preserved,
37
+ including the version emitted by Xcode 27. Unknown versions and unsupported
38
+ localization structures fail explicitly.
39
+
40
+ Plural/device variants and substitutions are supported. Target plural categories
41
+ are expanded from the source fallback; existing authored categories remain.
42
+ Apple printf tokens are protected automatically. Xcode `new` and `needs_review`
43
+ values remain pending; accepted generated values are marked `translated`.
44
+ Scaffolded values are marked `new` and still require a sync.
45
+
46
+ Existing locale-specific device and plural variants may vary a plain source
47
+ message. Named substitutions require matching definitions in the source
48
+ localization: a target-only `%#@count@` fragment cannot be safely inferred from
49
+ a flat source such as `Found %lld birds`. The adapter reports the affected key
50
+ and substitution before translation. Define the corresponding source
51
+ substitution in Xcode, including its plural fragments, then sync again.
52
+ Named substitutions may reorder in translations: their source `argNum` bindings
53
+ keep each reference attached to the same runtime argument. Ordinary printf
54
+ arguments still require compatible types and explicit positions when reordered.
55
+
56
+ For literal percentages that resemble format directives, such as `100% done`,
57
+ set `plainTextKeys: ["progress"]` on either Apple adapter, using the exact
58
+ resource lookup key. Those keys use the core plain message format; every other
59
+ key keeps printf protection. The setting applies to all variants of a catalog
60
+ key and to matching keys in every table selected by that adapter. Use it only
61
+ for messages without runtime printf arguments or named substitutions: literal
62
+ text and directives cannot be distinguished reliably from their spelling.
63
+
64
+ Paths for `--include-path` are locale-independent JSON pointers, for example
65
+ `/welcome/stringUnit/value` or
66
+ `/items/variations/plural/few/stringUnit/value`. Escape key slashes as `~1` and
67
+ tildes as `~0`. A path-scoped run requires an existing target document; first
68
+ scaffold it or perform an initial full sync. Seeding a new structured message may
69
+ create required fallback arms marked `new`; those are not accepted translations.
70
+
71
+ ## Legacy strings tables
72
+
73
+ ```ts
74
+ import { createAppleStringsCatalog } from "@ai-translate/apple";
75
+
76
+ const tables = createAppleStringsCatalog({
77
+ id: "legacy",
78
+ rootDir: "App/Resources", // contains en.lproj, de.lproj, ...
79
+ sourceLocale: "en",
80
+ // sourceLocaleDirectory: "Base.lproj",
81
+ // include: ["Localizable.strings", "InfoPlist.strings"],
82
+ });
83
+ ```
84
+
85
+ Units are table paths relative to the source `.lproj` directory, including the
86
+ `.strings` suffix. Entry paths are `/<key>`. The adapter handles UTF-8 with or
87
+ without BOM and UTF-16 in either byte order. It preserves existing formatting,
88
+ comments, encoding, and unrelated target keys; it rejects ambiguous duplicate
89
+ keys and malformed syntax. Key-only entries (`"Hello";`) and optional dictionary
90
+ braces are supported. Apple printf validation is automatic here too.
91
+
92
+ ## Discovery and composition
93
+
94
+ `ai-translate init --integration apple --preview` inspects native resources,
95
+ Xcode projects, and Apple Swift packages without executing project code. Projects
96
+ without catalogs receive explicit extraction/setup warnings. `init` writes only
97
+ the configuration; it does not edit Xcode projects or extract hardcoded text.
98
+
99
+ Generated configs list the authored files found during detection. Mixed
100
+ `Base.lproj` and source-locale tables are partitioned without translating the
101
+ same table twice. Nested projects with another declared source language are
102
+ reported for separate configuration. Expo native trees follow their ancestor
103
+ ignore rules; compiled app/framework bundles and build folders are excluded.
104
+
105
+ When no usable resources exist, the starter has `include: []`. After adding or
106
+ repairing resources, run `init --preview` and update the include lists from its
107
+ output. Legacy directory names such as `French.lproj` or `pt_BR.lproj` need
108
+ manual setup or migration to language tags such as `fr` and `pt-BR`.
109
+
110
+ `appleIntegration` implements the platform-neutral `Integration` interface from
111
+ `@ai-translate/integrations`. Both adapters implement `CatalogAdapter`, so they
112
+ compose with existing JSON, HTML, or Markdoc adapters and every provider.
113
+
114
+ Use the [native app guide](../../docs/native-apps.md) for a full configuration and
115
+ specific Swift package, shared iOS/macOS, Expo, and Tauri setup recipes. For Expo
116
+ prebuild, translate committed locale JSON using `applePrintfMessageFormat` from
117
+ `@ai-translate/message-formats`; preserve generated iOS resources through Expo's
118
+ own build workflow.
119
+
120
+ The CLI stages resource and state writes together. It checks for changes to live
121
+ files before committing and aborts if they were edited during translation; rerun
122
+ to use those edits. Use `sync --dry-run` to plan,
123
+ `adopt` to migrate existing translations, and `check` as a read-only CI gate.
124
+ Direct programmatic adapter writes are atomic per file, not across an entire
125
+ configuration; use the CLI when you need the transaction guarantee.
126
+
127
+ Legacy `.stringsdict`, XLIFF, source rewriting, and runtime lookup installation
128
+ are outside this package. Xcode can migrate legacy plural files into string
129
+ catalogs. Runtime layout and bundle membership still need app-level validation.
@@ -0,0 +1,38 @@
1
+ import { Integration } from "@ai-translate/integrations";
2
+ import { CatalogAdapter } from "@ai-translate/core/types";
3
+ //#region src/xcstrings.d.ts
4
+ interface AppleStringCatalogOptions {
5
+ id?: string;
6
+ /** Glob patterns relative to rootDir. Defaults to all authored .xcstrings. */
7
+ include?: readonly string[];
8
+ /** Exact catalog keys whose percent signs are literal text, not runtime printf arguments. */
9
+ plainTextKeys?: readonly string[];
10
+ rootDir: string;
11
+ /** Must match each catalog's sourceLanguage exactly. */
12
+ sourceLocale: string;
13
+ }
14
+ /** Native Xcode catalogs: one physical file, independently reconciled locales. */
15
+ export declare function createAppleStringCatalog(options: AppleStringCatalogOptions): CatalogAdapter;
16
+ //#endregion
17
+ //#region src/strings.d.ts
18
+ interface AppleStringsCatalogOptions {
19
+ id?: string;
20
+ /** Glob(s) relative to the source locale directory; all nested tables by default. */
21
+ include?: string | readonly string[];
22
+ /** Exact keys whose percent signs are literal text, not runtime printf arguments. */
23
+ plainTextKeys?: readonly string[];
24
+ rootDir: string;
25
+ sourceLocale: string;
26
+ /** For projects whose source files are in Base.lproj. Defaults to <locale>.lproj. */
27
+ sourceLocaleDirectory?: string;
28
+ }
29
+ /** Translate .lproj tables without replacing comments or unrelated translations. */
30
+ export declare function createAppleStringsCatalog(options: AppleStringsCatalogOptions): CatalogAdapter;
31
+ //#endregion
32
+ //#region src/integration.d.ts
33
+ /** Native resources are shared by Swift, Objective-C, React Native and Expo
34
+ * prebuild projects, so discovery follows authored resources rather than a UI framework. */
35
+ export declare const appleIntegration: Integration;
36
+ //#endregion
37
+ export type { AppleStringCatalogOptions, AppleStringsCatalogOptions };
38
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/xcstrings.ts","../src/strings.ts","../src/integration.ts"],"mappings":";;;UAciB;EACf;;EAEA;;EAEA;EACA;;EAEA;;;wBA6Bc,yBAAyB,SAAS,4BAA4B;;;UCtC7D;EACf;;EAEA;;EAEA;EACA;EACA;;EAEA;;;wBAsEc,0BAA0B,SAAS,6BAA6B;;;;;qBCiInE,kBAAkB"}