1.1.0 • Published 6 months ago

@drone1/alt v1.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

Run Tests Claude ChatGPT Gemini Node.js Contributions Welcome License: MIT

Demo

AI Localization Tool

Translates all source strings in a reference (js,mjs,json,jsonc) file to all target languages using AI.

Features

  • Loads source/reference key/value pairs from a file
  • Localizes using AI as needed, writing to a .json file per language
  • App-level context can be specified appContextMessage
  • Additional context can be specified per string --contextPrefix, --contextSuffix
  • Supports Claude, Gemini, OpenAI --provider
  • User-modifications to output files are safe and will not be overwritten
  • Languages are specified using BCP47 tags

Installation

npm install -g @drone1/alt

Setup

Create a reference file

This will house your source strings via key/value pairs in your preferred language.

Here's an example reference.js:

export default {
	'error-msg': `Sorry, we don't know how to do anything`,
	'success-msg': `A massive "achievement"`,
	'_context:success-msg': `This text is for a button when a user completes a task`
}

Use whatever filename you prefer. js,mjs,json,jsonc extensions are supported.

For .js and .mjs files, you can specify the name of an exported variable instead of using default, via --referenceVarName.

Running

ANTHROPIC_API_KEY=<secret>
alt translate --reference-file ./reference.js --reference-language en --target-languages aa,bo,es-MX,hi,zh-Hans --provider anthropic

This command would iterate across all key/value pairs defined in ./reference.js and translate if needed.

Here are all supported providers and their required environment variables:

-p, --providerenvironment variable
anthropicANTHROPIC_API_KEY
googleGOOGLE_API_KEY
openaiOPENAI_API_KEY

Output

The example above would write aa.json, bo.json, etc., to the current working directory.

Sample output:

{
	"error-msg": "དགོངས་དག་ང་ཚོས་ག་རེ་བྱེད་དགོས་མིན་ཤེས་ཀྱི་མི་འདུག",
	"success-msg": "གྲུབ་འབྲས་\"ཆེན་པོ་\"ཞིག"
}

Note that output files can be lower-cased if you pass the --normalize-output-filenames option, so fr-FR translations would write to fr-fr.json

Config file

optional For convenience, a config file is supported. You can use a config file in conjunction with command-line arguments.

Command-line arguments override config file values.

If no explicit config file is specified via --config-file, ALT will search for a file with the name alt.config.json in the current working directory.

If no config is loaded, you'll need to specify --reference-file and --provider, otherwise ALT will fail.

Here's an example alt.config.json file you might keep in your project's root directory:

{
	"appContextMessage": "This is a description of my app",
	"referenceLanguage": "ar",
	"provider": "google",
	"lookForContextData": true,
	"contextPrefix": "_context:",
	"contextSuffix": "",
	"outputDir": "localization",
	"referenceFile": "localization/reference.js",
	"targetLanguages": [
		"es-MX", "zh-SG"
	]
}

Since in most cases these arguments will not change often, a config file is recommended.

Any of the above settings can be specified using command-line arguments, but note the mapping from camelCase to kebab-case (appContextMessage => --app-context-message, referenceLanguage => --reference-language, etc.).

Adding context

Sometimes a string isn't enough to give context to the AI, and as a result, it may give an undesirable translation. ALT allows you to specify additional context for this reason.

Application-level context

A global, application description can be specified --app-context-message (or appContextMessage in a config). For example, your config may include something like:

	"appContextMessage": "Voided is a MMORPG game based on outer space."

String-specific context

Context can be added for any reference key/value pairs by passing --look-for-context-data (or setting lookForContextData: true in a config).

For example, given the following reference key/value pair:

	"editor-add-component": '+ Star',

This may not translate as desired, so ALT allows you to specify additional context in the form of another key/value pair. For example:

	"_context:editor-add-component": "This is text for a button the galaxy UI, where a user can create a star"

_context: can be whatever you prefer here. It's specified via --context-prefix, or contextPrefix in a config.

A suffix can be specified instead of (or in conjunction with) a prefix, with --context-suffix, or contextSuffix in a config. Example:

	"editor-add-component[context]": "This is text for a button the graph editor"

In this case, [context] would be specified by passing --context-suffix '[context]' or setting "contextSuffix": "[context]" in a config.

Further examples can be found here.

Display language

ALT CLI itself has been localized so you can use it many languages. You can optionally set the display language with the ALT_LANGUAGE environment variable. Please feel free to submit an issue if you do not see your preferred language.

Usage

Usage: alt [options] [command]

An AI-powered localization tool

Options:
  -V, --version          output the version number
  -h, --help             display help for command

Commands:
  translate [options]
  list-models [options]
  help [command]         display help for command

Environment variables:
  ANTHROPIC_API_KEY                     Your Anthropic API key
  OPENAI_API_KEY                        Your OpenAI API key
  GOOGLE_API_KEY                        Your Google Gemini API key
  ALT_LANGUAGE                          BCP47 language tag used for display

---

Usage: alt translate [options]

Options:
  -c, --config-file <path>                      Path to config file; defaults to <output dir>/alt.config.json
  -r, --reference-file <path>                   Path to reference file of source strings to be translated. This file can be in .js, .mjs, .json, or .jsonc formats and is presumed to be in the reference language specified by --reference-language; overrides any 'referenceFile' config setting
  -o, --output-dir <path>                       Output directory for localized files; overrides any 'outputDir' config setting
  -rl, --reference-language <language>          The reference file's language; overrides any 'referenceLanguage' config setting
  -tl, --target-languages <list>                Comma-separated list of language codes; overrides any 'targetLanguages' config setting
  -k, --keys <list>                             Comma-separated list of keys to process; if none are processed, all keys in the reference file will be processed
  -R, --reference-exported-var-name <var name>  For .js or .mjs reference files only, this will be the exported variable, e.g. for 'export default = {...}' you'd use 'default' here, or 'data' for 'export const data = { ... }'. For .json or .jsonc reference files, this value is ignored. (default: "default")
  -m, --app-context-message <message>           Description of your app, to be passed along to the AI, per translation request; overrides any 'appContextMessage' config setting
  -f, --force                                   Force regeneration of all keys; if no '--keys' argument is specified, all keys will be processed (default: false)
  -rtw, --realtime-writes                       Write updates to disk immediately, rather than on shutdown (default: false)
  -y, --tty                                     Use tty/simple renderer; useful for CI (default: false)
  -M, --model <name>                            LLM model name to use; defaults are: for "anthropic": "claude-3-7-sonnet-20250219", for "google": "gemini-2.0-flash", for "openai": "gpt-4-turbo"; use the 'list-models' command to view all models
  -x, --max-retries <integer>                   Maximum retries on failure (default: 3)
  -n, --normalize-output-filenames              Normalizes output filenames (to all lower-case); overrides any 'normalizeOutputFilenames' in config setting (default: false)
  -N, --no-logo                                 Suppress logo printout
  -cp, --context-prefix <value>                 String to be prefixed to all keys to search for additional context, which are passed along to the AI for context
  -cs, --context-suffix <value>                 String to be suffixed to all keys to search for additional context, which are passed along to the AI for context
  -L, --look-for-context-data                   If specified, ALT will pass any context data specified in the reference file to the AI provider for translation. At least one of --contextPrefix or --contextSuffix must be specified (default: false)
  -v, --verbose                                 Enables verbose spew; forces --tty mode (default: false)
  -d, --debug                                   Enables debug spew; forces --tty mode (default: false)
  -t, --trace                                   Enables trace spew; forces --tty mode (default: false)
  --dev                                         Enable dev mode, which prints stack traces with errors (default: false)
  -p, --provider <name>                         AI provider to use for translations (anthropic, openai); overrides any 'provider' config setting
  -h, --help                                    display help for command

---

Usage: alt list-models [options]

Options:
  -p, --provider <name>  AI provider to use for translations (anthropic,
                         openai); overrides any 'provider' config setting
  -h, --help             display help for command

Examples

Example I: ALT's localized display strings

The best example is probably the localization for ALT's own display strings.

See alt.config.js, which contains a config.js file and localization files used for the tool's own display strings.

Generated with npm run localize-display-strings

Example II

alt translate --reference-file loc.js
--reference-var-name data
--provider anthropic
--look-for-context-data
--context-prefix _context:
  • Imports reference strings from loc.js
  • Looks for exported variable data (if loc.js has export data = { ... })
  • Translates with Claude
  • Looks for context keys starting with _context:
  • Writes output files to the current working directory

Example III

alt translate --config-file ./localization-config.json
  --reference-file loc.js
  --output-dir localization
  --provider openai
  --look-for-context-data
  --context-suffix "[context]"
  • Imports config from ./localization-config.json
  • Imports reference strings from loc.js
  • Looks for exported default value
  • Translates with ChatGPT
  • Looks for context keys ending with [context]
  • Writes to disk repeatedly, as changes are processed
  • Writes files to ./localization

Example III

alt translate --config-file config.json
  --reference-file localization/reference/source.js
  --output-dir localization/output
  --provider openai
  --target-languages vi,aa
  --keys error-msg,title-hero,button-text-send
  • Overrides any target languages specified in the config
  • Only processes the specified keys (error-msg, etc.)

Formatting

If your reference values include formatting information like this:

"error-msg": "The server returned an error: %%details%%"

or

"error-msg": "The server returned an error: {{details}}"

...or whatever syntax your app may use for formatting, the AI's consistently smart enough not to translate %%details%% or {{details}} into the target language, and will leave it untouched.

Internally, there is currently nothing in the prompt about this. I've tested with %%var%% syntax, and it hasn't failed yet.

Please submit an issue if it causes you any trouble.

Translation rules

Under what conditions will ALT translate a given source string?

Translation will occur for a given target language & reference key/value if any of the following are true:

  • The output file does not exist
    • Example: You're translating to target language zh-Hans and zh-Hans.json doesn't exist
  • The output file is missing the reference key
    • Example: You're translating reference key error-msg to target language zh-Hant.jso and zh-Hans.json does not have a key/value pair for key error-msg
  • The reference value was modified
    • Example: You change the value of some-key in your reference file
  • A context value for the given target language/key is found and has been modified
    • Example: You modify the value of context:error-msg in your reference file. error-msg will be re-translated for all target languages.
  • -f or --force are specified
  • The cache file (.localization.cache.json) is not present

NOTE: Translation will not occur if ALT detects that the given value in the target language file has been manually modified. If you modify an output value manually and want it to be re-translated later, you can just delete that key/value pair from the given file.

Additional notes

Yes, you should commit your .localization.cache.json

If you do not do this, you'll lose important state and need to re-translate everything.

Delayed vs. realtime writes

By default, ALT will not write to disk until the tool is shutting down (including SIGTERM yes, Ctrl+C is safe).

This behavior is useful if your application is monitoring the output directory and you don't want your server constantly restarting, for example.

If you prefer to write updates to disk in real-time (anytime any output data changes, due to translation, etc), you can pass --realtime-writes.

CI

You may want to use --tty for more useful output.

Contributing

Feel free to fix existing issues and submit a PR, or submit a new issue.

Feedback

Feedback is more than welcome. Please feel free to create an issue.

1.1.0

6 months ago

1.0.4

6 months ago

1.0.3

6 months ago

1.0.2

6 months ago

1.0.1

6 months ago

1.0.0

6 months ago

0.9.4

6 months ago

0.9.3

6 months ago

0.9.2

6 months ago

0.9.1

6 months ago

0.9.0

6 months ago

0.8.1

6 months ago

0.8.0

6 months ago

0.7.2

6 months ago

0.7.1

6 months ago

0.7.0

6 months ago

0.4.2

6 months ago

0.4.1

6 months ago

0.4.0

6 months ago