Crowdin
Use Crowdin for MainSDK translations - project setup, main.yaml, locales, missing strings caught by the check, local testing and swapping.
Crowdin is a localization management platform where translators, reviewers and vendors work on your strings. Behind i18n, it holds your app's translations while your code keeps calling t() and i18n.format.*. Pick Crowdin when you work with professional translators or a translation agency, or when many languages and contributors make plain locale files hard to manage.
Interfaces it serves
Pick Crowdin in main.yaml for any of these. Your calls stay the same, and you can swap later.
i18nPreviewDriver crowdin Crowdin
i18n:
driver: crowdinSwap to another provider
Before you start
- Create a Crowdin project with your source language and the target languages you ship, such as Hindi and Tamil.
- Create an access token with access to that project, and note the project's ID.
- Invite translators or connect a vendor, and set up any glossary and translation memory you want shared.
- Store the token in your secrets manager, never in code or a committed env file.
Configure
i18n:
driver: crowdin
locales: [en-IN, hi-IN, ta-IN] # the locales you ship
# [to be decided] project ID, and the access token as secret:CROWDIN_TOKENLocales fall back along a chain: hi-IN, then hi, then en-IN, then en. A market overlay can set its own locales; see main.yaml.
Use it
import { i18n, t } from "mainsdk";
export function heading(orders: unknown[]) {
const title = t("orders.count", { count: orders.length });
const total = i18n.format.money(125000, "INR"); // ₹1,25,000 in en-IN
return `${title} · ${total}`;
}Messages use Unicode MessageFormat 2 with ICU fallback for plurals, genders and selections; formats come from Unicode CLDR, not from Crowdin.
Local development and testing
- Local files: the default
filesdriver readslocales/<locale>.yaml, so you can build and test with no Crowdin project. Switch tocrowdinwhen translators join. - Tests:
createTestApp()from@mainsdk/testingrunsi18nwithout a network, andchaos.on("i18n", { outage: true })simulates Crowdin being unreachable.
What MainSDK adds on top
- A missing translation fails
mainsdk check, not the user. mainsdk checkruns pseudo-localization (long strings, accents, right-to-left) to catch layout breaks before a translator sees them.- Formats from Unicode CLDR, and the locale from the user's choice first, never guessed from IP alone.
- Android and iOS string files generated from the same locales.
See Languages and formats for the full contract.
Limits and notes
- Planned driver from the product requirements;
i18nhas no spec yet. - How strings sync between your repo and Crowdin, and when translations reach a running app, are not defined yet.
- Translations in XLIFF, iOS
.xcstrings, Android strings and ICU JSON import and export (byo-content), which helps when moving strings in or out of Crowdin.
Swap to or from it
i18n:
driver: crowdin # was filesYour t() and i18n.* calls stay the same.
FAQ
Do I need Crowdin to start? No. Start with the files driver and move to Crowdin when you add translators.
Can I use AI drafts with Crowdin? MainSDK's AI drafts come with the separate ai-draft driver. Whether it combines with crowdin is not decided yet.
Next
Open questions
Was this page helpful?