next-intl
Fink edits next-intl message files in your GitHub repository: the messages/{locale}.json files that useTranslations and getTranslations read. You see each message's translations side by side, Fink flags missing ones and broken plurals, variables or tags, and it commits only the lines you changed.
Set up
Add project.inlang/settings.json next to your app's package.json. Paths are relative to the folder that contains project.inlang:
{
"$schema": "https://inlang.com/schema/project-settings",
"baseLocale": "en",
"locales": ["en", "de", "fr"],
"modules": [
"https://cdn.jsdelivr.net/npm/@inlang/plugin-next-intl@2/dist/index.js"
],
"plugin.inlang.nextIntl": {
"pathPattern": "./messages/{locale}.json"
}
}
List the locales of your routing.ts in locales. baseLocale is the language you write first, usually your defaultLocale. Commit the folder and open the repository at fink.inlang.com.
Files per namespace
If you split messages into one file per namespace, give pathPattern one entry per namespace:
"plugin.inlang.nextIntl": {
"pathPattern": {
"HomePage": "./messages/{locale}/home.json",
"Checkout": "./messages/{locale}/checkout.json"
}
}
The messages of ./messages/en/home.json appear as HomePage.title and so on, as useTranslations("HomePage") reads them. Fink writes each one back to its own file. A new message must start with one of the namespaces, such as HomePage.subtitle: Fink can't push a message that has no file.
What Fink understands
- Namespaces.
{ "Home": { "title": "…" } }is the messageHome.title, ast("Home.title")oruseTranslations("Home")reads it. A new message is nested at its dots. - Arguments.
{name}appears as the variable{name}. - Plurals.
{count, plural, =0 {…} one {# item} other {# items}}appears as one message with a form for exactly 0 and the plural forms each language needs, for examplefewandmanyin Polish.#is the number. Any exact number (=0,=1,=12) works. See Plurals, selects and exact numbers. - Selects and ordinals.
{gender, select, female {…} other {…}}and{place, selectordinal, one {#st} …}work the same way, also nested in each other. - Rich text. Tags such as
<b>…</b>and<link>…</link>, fort.rich()andt.markup(), are shown as tags that translators can keep, move or wrap around text. Fink flags a translation that lost one. - Number and date formats.
{price, number, ::currency/EUR}and{date, date, short}are kept as written. - Escaping. Quoted text like
'{name}'shows as{name}. When you type{or a tag as text, Fink quotes it so that next-intl shows it as text.
Arrays and other values that aren't messages (for t.raw()) are kept in the files but not shown.
Small diffs
Fink writes only the messages you changed. Every other line of the file, its key order, indentation and quoting, stays byte for byte. A plural you edit is written as one ICU string, such as {count, plural, =0 {No items} one {# item} other {# items}}.
Limitations
- Unused messages are not detected for next-intl projects. Fink's code analysis only understands Paraglide JS calls.
- Tags around a plural, such as
<b>{count, plural, …}</b>, are written into each form,{count, plural, one {<b>…</b>} …}, once you edit the message. next-intl renders both the same. - Self-closing tags like
<br/>are text in next-intl. Use<br></br>. - A message next-intl can't parse is shown as text and written back as it was, unless you edit it.
- With
sourceLanguageFilePath, the file of the reference locale, change the reference locale insettings.jsonin your repository, not in Fink.