--- title: Introduction tags: project-fluent --- # Introduction **Project Fluent** is a localization/translation framework for Stardew Valley / SMAPI. Its main features are: * Support for FTL files -- [Project Fluent](https://projectfluent.org/) created by Mozilla. * Multiple separate FTL files per mod (unlike SMAPI's base i18n implementation). * Using Fluent translations in C#/SMAPI mods via [the mod API](https://github.com/Shockah/Stardew-Valley-Mods/blob/dev/fluent/ProjectFluent/PublicAPI/IFluentApi.cs). * Using Fluent translations in Content Patcher mods via a `{{Fluent}}` token. * Support for locale variants (differentiating between `en-US` and `en-GB`, but also providing a default `en` variant). * Loading custom translations (and also allowing overriding of existing translations) for arbitrary mods -- both Fluent and i18n. Source code: https://github.com/Shockah/Stardew-Valley-Mods/tree/master/ProjectFluent # Why Fluent instead of i18n? i18n-based localization is fine for basic use cases, but most languages unfortunately are not that simple. ## Plurality Let's say you want to tell the player they have a certain number of items. To build grammatically-correct sentences for this, you need to know how many of the items they have beforehand and choose the proper translation: ```json { "itemCount-one": "You have 1 item.", "itemCount-other": "You have {{ItemCount}} items." } ``` At first glance this works just fine, but if you try to use the same translations file for a different language, this breaks. Polish, for example, would require those translations: ```json { "itemCount-one": "Masz 1 przedmiot.", "itemCount-two-to-four": "Masz {{ItemCount}} przedmioty.", "itemCount-other": "Masz {{ItemCount}} przedmiotów." } ``` The Unicode Common Locale Data repository contains [a set of language plural rule data](https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html) to solve this problem. Mozilla's Project Fluent uses this CLDR plural rule data. To solve the above problem with Fluent translations, you would define only one key, and different translations could handle this separately: ```ftl # en.ftl itemCount = You have {$ItemCount -> [one] 1 item *[other] {$ItemCount} items }. # pl.ftl itemCount = Masz {$ItemCount -> [one] 1 przedmiot [few] {$ItemCount} przedmioty *[other] {$ItemCount} przedmiotów }. ``` ## Grammatical cases In many languages the proper grammatical form of a word also depends on the *context* the word is being used in. For example, the word "apple". In English, you do not change its form at all: * "I have an apple." * "I don't like the taste of this apple." * "I threw the apple." In Polish though, the grammatical form of the equivalent word "jabłko" has to be changed depending on the context: * "Mam jabłko." * "Nie lubię smaku tego jabłka." * "Rzuciłem jabłkiem." This can also be solved with Fluent translations. See [the Mozilla's Project Fluent page](https://projectfluent.org/) for more details. ## Other problems Project Fluent also easily solves gendered translations, different capitalization rules, etc. Again, see [the Mozilla's Project Fluent page](https://projectfluent.org/) for more details.