ni81 (pronounced "nibble") is a tool to manage your static i18n files and integrate local LLMs for translations. It addresses the challenge of managing static translation files, particularly those used by frameworks like Next.js - primarily via the next-intl plugin.
The desired workflow with ni81 is
graph TB
A(Make changes to default locale file) -->B[Run ni81]
B -->C(ni81 detects changes, translates those, and propagates them to the other locale files)
Build from source using make build or download one of the released binaries.
Currently ni81 only supports translations through models available that support the OpenAI API standard. The most convenient option is to run a model locally through ollama.
You will need to initialise your project in the project's root directory
nibl init
This will produce a TOML (ni81.toml) file in your project's root directory (which you should commit to your VCS).
If for any reason this file becomes corrupted you can remove it and re-run init, this will not effect the
existing translations provided by ni81. The initialise process will also order any existing JSON files (to avoid
clutter in future diffs when performing translations) and generate a file cache to use as a source of truth.
As with the generated config file you should also commit the file cache to your VCS.
In addition to the config created by nibl init a file cache (<default_locale>.cache.json) is created to
act as a source of truth. This should also be commited to your VCS as it is necessary to determine what keys
are added, modified, or removed, in the future. If at any point you need to recreate your cache you can use
nibl cache
Warning
Recreating your cache will make the default locale file, at the time of the new cache creation, the source of truth moving forward.
Once the project has been initialised ni81 will make translations based on changes to your default locale file. To translate use
nibl translate
This will translate the default locale to all supported locales in your project's ni81.toml file. If there
is a failure in any key-value pair of a locale, the entire locale will be skipped. Moreover, a failure will
cause the cache to not be updated so you can rerun translate. In some instances, you may want to perform
translations as if the cache is empty. For example, suppose you have a default locale file (en.json) populated with
{
"buttons": {
"login": "Login",
"submit": "Submit"
},
"banners": {
"alert": "Alert",
"warning": "Warning",
"info": "Info"
}
}
The cache (en.cache.json) created during project initialisation would be
{
"buttons.login": "Login",
"buttons.submit": "Submit",
"banners.alert": "Alert",
"banners.warning": "Warning",
"banners.info": "Info"
}
so any attempt to use nibl translate would result in nothing happening as it seems the source of truth
(en.cache.json) has the same keys as the flattened default locale file (en.json). In such a case, we can
pass a --clean flag
nibl translate --clean
so that translations run assuming the cache is empty, that is, the contents of en.cache.json are {}.
ni81 offers a diff command to show what keys have been added, modified, or deleted in your JSON. Using the example
{
"buttons": {
"login": "Login",
"submit": "Submit"
},
"banners": {
"alert": "Alert",
"warning": "Warning",
"info": "Info"
}
}
if we
- modify the
"buttons.login"value to"Sign in", - add
"buttons.save": "Save"and, - delete the
"banners.warning"key,
the nibl diff command will print
-"banners.warning": "Warning"
-"buttons.login": "Login"
+"buttons.login": "Sign in"
+"buttons.save": "Save"
- User input validation during initialisation
- Search up through parent directories (to file system root) for config file to allow use of
niblthroughout all subdirectories of a project - Create cache from
<default_locale>.jsonif it exists - Flag to run translations as if cache is empty
- File cache for each supported locale for improved failure handling during translation
- Expand LLM support to remote through web API that follow OpenAI standard
- Local glossary (on flattened JSON keys) management for translations
- Locale flag for
translationto translate to specified locale - Improved error logging. For example, if there is malformed JSON this should be reported clearly.
- Expand test coverage
- Allow for sensitive information storage away from
tomlconfig file - Expand remote OpenAI API support:
- Adding support for bearer authentication
- Custom model prompt when using
generateendpoint - Custom body values for model options, such as,
think,keep_alive,optionsetc. - Use of endpoints other than
generate
- Add
diffcommand to log keys that are- added
- modified
- deleted