Talkr
Talkr is the lightest i18n provider for React applications. It supports Typescript, provides autocompletion, has 0 dependencies, and is very easy to use.
Install / Use
/learn @DoneDeal0/TalkrREADME
<img width="1015" alt="Capture d’écran 2024-05-20 à 17 19 54" src="https://github.com/DoneDeal0/Talkr/assets/43271780/55fb8790-13ee-4273-a113-8cc5478912da"></img>
<hr/>TALKR
Talkr is the lightest i18n provider for React applications. It supports Typescript, provides autocompletion, has 0 dependencies, and is very easy to use.
<hr/>FEATURES
- Auto-detect browser language
- Auto-detect plural rules based on any language
- Dynamic translations with multiple keys
- Access deeply nested keys in json translations files
- Adapts syntax to gender
- Supports lists
- Supports React Native
- Provides typescript autocompletion for your keys
SCREENSHOT
<img width="588" alt="talkr autocomplete in action" src="https://user-images.githubusercontent.com/43271780/154273252-f0818de8-66d1-4265-9e6f-bebe5bd8b73f.png"></img>
<hr/>INSTALLATION
// with npm
npm install talkr
// with yarn
yarn add talkr
<hr/>
ADD TRANSLATION FILES
- Create your JSON translation files.
- Surround dynamic values by double underscores:
__dynamicValue__. - To allow automatic plural detection, you will need to pass a
countparameter to Talkr's translation function. Talkr will then chose the right word or sentence betweenzero,one,two,fewandmany.
🤓: Some languages have more complex plural rules, that may require these five options to offer a perfect user experience. For instance, Arabic handle
zero,one,two,numbers between 3 and 10andnumbers over 10as separate entities. If a language doesn't need all these subtleties - like english - you can only writezero,oneandmanyin the JSON file.
{
"hello": "hello",
"feedback": {
"error": "The connection failed",
"success": "The connection succedeed"
},
"user": {
"describe": {
"simple": "You are __name__",
"complex": "You are __name__ and you like __hobby__"
}
},
"idiom": {
"sovereign": {
"female": "Long live the Queen!",
"male": "Long live the King!"
}
},
"message-count": {
"zero": "you don't have new messages",
"one": "you have 1 message",
"many": "you have __count__ messages"
},
"days": ["Monday", "Tuesday", "Wednesday"],
}
<hr/>
SET UP
- In your index file, import your JSON translations
- Wrap your App with Talkr's
Provider - Pass it your available
languagesand yourdefaultLanguage. - You also have the option to let Talkr detect browser's language with the prop
detectBrowserLanguage(see [props](#Available props)).
import * as React from "react";
import { createRoot } from "react-dom/client";
import { Talkr } from "talkr";
import App from "./app";
import en from "./i18n/en.json";
import fr from "./i18n/fr.json";
const root = createRoot(document.getElementById("root"));
root.render(
<Talkr languages={{ en, fr }} defaultLanguage="en">
<App />
</Talkr>,
);
<hr/>
SIMPLE USAGE
- In any component, import Talker's hook
useT. - Destructure the translation function
TfromuseT - Fetch the desired sentence as if you were directly accessing an object, by adding
.between each key. Based on the JSON example above, we could print the sentenceThe connection succedeedby simply writingT("feedback.success")
import React from "react";
import { useT } from "talkr";
export default function MyComponent() {
const { T } = useT();
return (
<>
<h1>{T("hello")}</h1>
<div>{T("feedback.success")}</div>
</>
);
}
<hr/>
DYNAMIC VALUES
- To handle dynamic translations, just add an object with all necessary dynamic values
- To make it work, you need to surround the dynamic values by double underscores in your [JSON files](Add translation files) (
__dynamicValue__)
"user": {
"describe": {
"simple": "You are __name__",
"complex": "You are __name__ and you like __hobby__"
}
}
import React from "react";
import { useT } from "talkr";
export default function MyComponent() {
const { T } = useT();
return (
<>
<h1>{T("user.describe.complex", { name: "joe", hobby: "coding" })}</h1>
</>
);
}
<hr/>
PLURAL
- To handle plural, just add a
countproperty to the object - To make it work, you need to provide both
zero,oneandmanyvalues to your JSON files.
"message-count": {
"zero": "you don't have new messages",
"one": "you have 1 message",
"many": "you have __count__ messages"
}
import React, { useState } from "react";
import { useT } from "talkr";
export default function MyComponent() {
const { T } = useT();
const [count, setCount] = useState(0);
return (
<>
<h1>{T("message-count", { count })}</h1>
<button onClick={() => setCount(count + 1)}>+1</button>
</>
);
}
<hr/>
GENDER
- Some languages have different syntax for masculine and feminine genders.
- To adapt your sentence accordingly, just pass the param
gender: mformale, orgender: fforfemale. - To make it work, you need to provide both
maleandfemalevalues to your JSON files.
"idiom": {
"sovereign": {
"female": "Long live the Queen!",
"male": "Long live the King!"
}
}
import React from "react";
import { useT } from "talkr";
export default function MyComponent() {
const { T } = useT();
return (
<>
<h1>{T("idiom.sovereign", { gender: "m" })}</h1>
</>
);
}
LIST
- You can render a list of string
- The last junction can be styled thanks to the following parameters:
listType?: "conjunction" | "disjunction"; // ""conjunction" by default
listStyle?: "long" | "narrow"; // "narrow" by default
"days": ["Monday", "Tuesday", "Wednesday"],
import React from "react";
import { useT } from "talkr";
export default function MyComponent() {
const { T } = useT();
return (
<>
<h1>{T("days", { listType: "conjunction" })}</h1>
</>
);
}
<hr/>
LOCALE
- Access and update the locale by using the hook
useT() - If the provided locale doesn't match any JSON translation files, Talkr will use the
defaultLanguagesent to the provider.
import React, { useState } from "react";
import { useT } from "talkr";
export default function MyComponent() {
const { T, setLocale, locale } = useT();
return (
<>
<h1>{T("hello")}</h1>
<p>{locale}</p>
<button onClick={() => setLocale("fr")}>speak french</button>
</>
);
}
<hr/>
<a name='autocomplete'></a>
AUTOCOMPLETION
Autocompletion for translation keys is available in Typescript projects. Because json must be parsed at compile time, you will need to create your own useAutocompleteT hook with Talkr's Autocomplete type wrapper.
Here's how to do it:
- Make sure you use
Typescript >=4.5.5(we don't guarantee it will work on older versions) - Create a
translate.tsxfile anywhere in your app(translate.tsxcan be named as you want) - Import your main language JSON translation (ex:
en.json) - Instantiate autocompletion with Talkr's
Autocomplete - Export a
useAutocompleteThook around Talkr'suseT()
import { useT, Autocomplete, TParams, tr } from "talkr";
import en from "./en.json";
type Key = Autocomplete<typeof en>;
export const useAutocompleteT = () => {
const { locale, languages, defaultLanguage } = useT();
return {
T: (key: Key, params?: TParams) =>
tr({ locale, languages, defaultLanguage }, key, params),
};
};
If you prefer to keep the useT naming, just write:
import { useT as useTr, Autocomplete, TParams, tr } from "talkr";
import en from "./en.json";
type Key = Autocomplete<typeof en>;
export const useT = () => {
const { locale, languages, defaultLanguage } = useTr();
return {
T: (key: Key, params?: TParams) =>
tr({ locale, languages, defaultLanguage }, key, params),
};
};
Autocomplete usage
You now have the choice between using your own useAutocompleteT hook - which provides real-time autocompletion - or using Talkr's useT - which doesn't provide autocompletion - in your app.
import { useAutocompleteT } from "./translate";
function App() {
const { T } = useAutocompleteT();
return (
<>
<h1>{T("feedback.success")}</h1>
<h4>{T("user.describe.complex", { name: "joe", hobby: "coding" })}</h4>
</>
);
}
🤓 Pro-tip: since you will need to import
useAutocompleteTfromtranslate.tsx, it is highly recommended to add an aliastranslateto your builder's config andtsconfig.json.
This will allow you to write
import { useAutocompleteT } from "translate" 👍
instead of
import { useAutocompleteT } from "../../translate" 👎
<hr/>Exemples: webpack
resolve: { extensions: [".ts", ".tsx", ".js", "jsx", ".json"], alias: { translate: path.resolve(__dirname, "src/translate/"), }tsconfig
{ "compilerOptions": { "paths": { "translate/*": ["src/translate/*"] } }}for other bundlers, please refer to their respective documentations.
REACT NATIVE
- Add your provider directly in App.(js|tsx)
import { StyleSheet, Text, View } from "react-native";
import { Talkr } from "talkr";
import en from "./src/i18n/en.json";
import fr from "./src/i18n/fr.json";
import MyComponent from "./src/MyComponent";
export default function App() {
return (
<Talkr la
