@ttoss/react-i18n 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # @ttoss/i18n
2
+
3
+ ## About
4
+
5
+ **@ttoss/react-i18n** is a library that provides a simple way to internationalize your React application using ttoss ecosystem.
6
+
7
+ ## Get Started
8
+
9
+ ### Install @ttoss/i18n
10
+
11
+ ```shell
12
+ yarn add @ttoss/react-i18n
13
+ ```
14
+
15
+ ## Examples of use
16
+
17
+ ### Index.tsx
18
+
19
+ Import the I18nProvider and wrap your application with it. Add to it a function called `loadLocaleData` to load all the translation data.
20
+
21
+ ```tsx title="src/index.tsx"
22
+ import { I18nProvider, LoadLocaleData } from '@ttoss/react-i18n';
23
+
24
+ const loadLocaleData: LoadLocaleData = (locale) => {
25
+ switch (locale) {
26
+ case 'pt-BR':
27
+ return import('../i18n/compiled-lang/pt-BR.json');
28
+ default:
29
+ return import('../i18n/compiled-lang/en.json');
30
+ }
31
+ };
32
+
33
+ ReactDOM.render(
34
+ <I18nProvider
35
+ locale={window.navigator.language}
36
+ loadLocaleData={loadLocaleData}
37
+ >
38
+ <App />
39
+ </I18nProvider>,
40
+ document.getElementById('root')
41
+ );
42
+ ```
43
+
44
+ ### App.tsx
45
+
46
+ Then import the useI18n hook and extract the intl, to get access to the `formatMessage` function and many others (using `defineMessages` is optional).
47
+
48
+ ```tsx title="src/App.tsx"
49
+ import { useI18n, defineMessages } from '@ttoss/react-i18n';
50
+
51
+ const messages = defineMessages({
52
+ myNameIs: {
53
+ description: 'My name is',
54
+ defaultValue: 'My name is {name}',
55
+ },
56
+ });
57
+
58
+ const App = () => {
59
+ const { intl, setLocale } = useI18n();
60
+
61
+ const [name, setName] = React.useState('Rayza');
62
+
63
+ return (
64
+ <div>
65
+ <div>
66
+ <button onClick={() => setLocale('en-US')}>en-US</button>
67
+
68
+ <button onClick={() => setLocale('pt-BR')}>pt-BR</button>
69
+ </div>
70
+
71
+ <input value={name} onChange={(e) => setName(e.target.value)} />
72
+
73
+ <h3>{intl.formatMessage(messages.myNameIs, { name })}</h3>
74
+ </div>
75
+ );
76
+ };
77
+
78
+ export default App;
79
+ ```
package/bin/cli.js ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { compile, extract } = require('@formatjs/cli');
4
+ const fs = require('fs');
5
+ const glob = require('glob');
6
+ const path = require('path');
7
+
8
+ const DEFAULT_DIR = 'i18n';
9
+
10
+ const EXTRACT_DIR = path.join(DEFAULT_DIR, 'lang');
11
+
12
+ const COMPILE_DIR = path.join(DEFAULT_DIR, 'compiled-lang');
13
+
14
+ const args = process.argv.slice(2);
15
+
16
+ (async () => {
17
+ /**
18
+ * Extract
19
+ */
20
+ const extractedDataAsString = await extract(glob.sync('src/**/*.{ts,tsx}'), {
21
+ idInterpolationPattern: '[sha512:contenthash:base64:6]',
22
+ });
23
+
24
+ await fs.promises.mkdir(EXTRACT_DIR, { recursive: true });
25
+
26
+ await fs.promises.writeFile(
27
+ path.join(EXTRACT_DIR, 'en.json'),
28
+ extractedDataAsString
29
+ );
30
+
31
+ if (args.includes('--no-compile')) {
32
+ return;
33
+ }
34
+
35
+ /**
36
+ * Compile
37
+ */
38
+ await fs.promises.mkdir(COMPILE_DIR, {
39
+ recursive: true,
40
+ });
41
+
42
+ const translations = glob.sync(EXTRACT_DIR + '/*.json');
43
+
44
+ for (const translation of translations) {
45
+ const filename = translation.split('/').pop();
46
+
47
+ const compiledDataAsString = await compile([translation], {
48
+ ast: true,
49
+ });
50
+
51
+ await fs.promises.writeFile(
52
+ path.join(COMPILE_DIR, filename),
53
+ compiledDataAsString
54
+ );
55
+ }
56
+ })();
@@ -0,0 +1,69 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+
3
+ // tsup.inject.js
4
+ import * as React from "react";
5
+
6
+ // src/index.ts
7
+ import { defineMessages, defineMessage, FormattedMessage } from "react-intl";
8
+
9
+ // src/i18Provider.tsx
10
+ import * as React2 from "react";
11
+ import { IntlProvider } from "react-intl";
12
+ import { Fragment, jsx } from "react/jsx-runtime";
13
+ var DEFAULT_LOCALE = "en";
14
+ var I18nConfigContext = React2.createContext({
15
+ defaultLocale: DEFAULT_LOCALE,
16
+ setLocale: () => {
17
+ return null;
18
+ }
19
+ });
20
+ var I18nProvider = ({
21
+ children,
22
+ locale: initialLocale,
23
+ loadLocaleData,
24
+ ...intlConfig
25
+ }) => {
26
+ const [locale, setLocale] = React2.useState(initialLocale || DEFAULT_LOCALE);
27
+ const [messages, setMessages] = React2.useState();
28
+ React2.useEffect(() => {
29
+ if (loadLocaleData) {
30
+ loadLocaleData(locale).then((message) => {
31
+ return setMessages(message);
32
+ });
33
+ }
34
+ }, [loadLocaleData, locale]);
35
+ return /* @__PURE__ */ jsx(I18nConfigContext.Provider, {
36
+ value: {
37
+ defaultLocale: DEFAULT_LOCALE,
38
+ locale,
39
+ setLocale,
40
+ ...intlConfig
41
+ },
42
+ children: /* @__PURE__ */ jsx(IntlProvider, {
43
+ defaultLocale: DEFAULT_LOCALE,
44
+ locale,
45
+ messages,
46
+ ...intlConfig,
47
+ children: /* @__PURE__ */ jsx(Fragment, {
48
+ children
49
+ })
50
+ })
51
+ });
52
+ };
53
+
54
+ // src/useI18n.ts
55
+ import * as React3 from "react";
56
+ import { useIntl } from "react-intl";
57
+ var useI18n = () => {
58
+ const intl = useIntl();
59
+ const config = React3.useContext(I18nConfigContext);
60
+ return { ...config, intl };
61
+ };
62
+ export {
63
+ DEFAULT_LOCALE,
64
+ FormattedMessage,
65
+ I18nProvider,
66
+ defineMessage,
67
+ defineMessages,
68
+ useI18n
69
+ };
@@ -0,0 +1,27 @@
1
+ import * as react_intl from 'react-intl';
2
+ export { FormattedMessage, defineMessage, defineMessages } from 'react-intl';
3
+ import * as React from 'react';
4
+
5
+ declare type MessagesType = any;
6
+ declare type LoadLocaleData = (locale: string) => Promise<MessagesType>;
7
+ declare type I18nProviderProps = {
8
+ locale?: string;
9
+ loadLocaleData?: LoadLocaleData;
10
+ children?: React.ReactNode;
11
+ };
12
+ /**
13
+ * `DEFAULT_LOCALE` must be `en` because is the default of the other modules.
14
+ */
15
+ declare const DEFAULT_LOCALE = "en";
16
+ declare const I18nProvider: ({ children, locale, loadLocaleData, ...intlConfig }: I18nProviderProps) => JSX.Element;
17
+
18
+ declare const useI18n: () => {
19
+ intl: react_intl.IntlShape;
20
+ locale?: string | undefined;
21
+ loadLocaleData?: LoadLocaleData | undefined;
22
+ children?: React.ReactNode;
23
+ defaultLocale: string;
24
+ setLocale: (language: string) => void;
25
+ };
26
+
27
+ export { DEFAULT_LOCALE, I18nProvider, I18nProviderProps, LoadLocaleData, useI18n };
package/dist/index.js ADDED
@@ -0,0 +1,106 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
26
+
27
+ // src/index.ts
28
+ var src_exports = {};
29
+ __export(src_exports, {
30
+ DEFAULT_LOCALE: () => DEFAULT_LOCALE,
31
+ FormattedMessage: () => import_react_intl3.FormattedMessage,
32
+ I18nProvider: () => I18nProvider,
33
+ defineMessage: () => import_react_intl3.defineMessage,
34
+ defineMessages: () => import_react_intl3.defineMessages,
35
+ useI18n: () => useI18n
36
+ });
37
+ module.exports = __toCommonJS(src_exports);
38
+
39
+ // tsup.inject.js
40
+ var React = __toESM(require("react"));
41
+
42
+ // src/index.ts
43
+ var import_react_intl3 = require("react-intl");
44
+
45
+ // src/i18Provider.tsx
46
+ var React2 = __toESM(require("react"));
47
+ var import_react_intl = require("react-intl");
48
+ var import_jsx_runtime = require("react/jsx-runtime");
49
+ var DEFAULT_LOCALE = "en";
50
+ var I18nConfigContext = React2.createContext({
51
+ defaultLocale: DEFAULT_LOCALE,
52
+ setLocale: () => {
53
+ return null;
54
+ }
55
+ });
56
+ var I18nProvider = ({
57
+ children,
58
+ locale: initialLocale,
59
+ loadLocaleData,
60
+ ...intlConfig
61
+ }) => {
62
+ const [locale, setLocale] = React2.useState(initialLocale || DEFAULT_LOCALE);
63
+ const [messages, setMessages] = React2.useState();
64
+ React2.useEffect(() => {
65
+ if (loadLocaleData) {
66
+ loadLocaleData(locale).then((message) => {
67
+ return setMessages(message);
68
+ });
69
+ }
70
+ }, [loadLocaleData, locale]);
71
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(I18nConfigContext.Provider, {
72
+ value: {
73
+ defaultLocale: DEFAULT_LOCALE,
74
+ locale,
75
+ setLocale,
76
+ ...intlConfig
77
+ },
78
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_intl.IntlProvider, {
79
+ defaultLocale: DEFAULT_LOCALE,
80
+ locale,
81
+ messages,
82
+ ...intlConfig,
83
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {
84
+ children
85
+ })
86
+ })
87
+ });
88
+ };
89
+
90
+ // src/useI18n.ts
91
+ var React3 = __toESM(require("react"));
92
+ var import_react_intl2 = require("react-intl");
93
+ var useI18n = () => {
94
+ const intl = (0, import_react_intl2.useIntl)();
95
+ const config = React3.useContext(I18nConfigContext);
96
+ return { ...config, intl };
97
+ };
98
+ // Annotate the CommonJS export names for ESM import in node:
99
+ 0 && (module.exports = {
100
+ DEFAULT_LOCALE,
101
+ FormattedMessage,
102
+ I18nProvider,
103
+ defineMessage,
104
+ defineMessages,
105
+ useI18n
106
+ });
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@ttoss/react-i18n",
3
+ "version": "1.17.0",
4
+ "license": "UNLICENSED",
5
+ "author": "ttoss",
6
+ "contributors": [
7
+ "Pedro Arantes <arantespp@gmail.com> (https://arantespp.com)",
8
+ "Rayza Oliveira Costa <rayza.ocr@gmail.com> (https://bio.link/rayza)"
9
+ ],
10
+ "main": "dist/index.js",
11
+ "module": "dist/esm/index.js",
12
+ "bin": {
13
+ "ttoss-i18n": "./bin/cli.js"
14
+ },
15
+ "files": [
16
+ "bin",
17
+ "dist",
18
+ "src"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "yarn workspace @ttoss/storybook run dev",
23
+ "pretest": "yarn run pretest:extract && yarn run pretest:compile",
24
+ "test": "jest",
25
+ "pretest:compile": "yarn run pretest:compile:en && yarn run pretest:compile:ptBR",
26
+ "pretest:compile:en": "formatjs compile i18n/lang/en.json --ast --out-file i18n/compiled-lang/en.json",
27
+ "pretest:compile:ptBR": "formatjs compile i18n/lang/pt-BR.json --ast --out-file i18n/compiled-lang/pt-BR.json",
28
+ "pretest:extract": "formatjs extract 'tests/**/*.ts*' --out-file i18n/lang/en.json"
29
+ },
30
+ "typings": "dist/index.d.ts",
31
+ "dependencies": {
32
+ "glob": "^8.0.3",
33
+ "react-intl": "^6.2.5"
34
+ },
35
+ "peerDependencies": {
36
+ "react": ">=16.8.0"
37
+ },
38
+ "devDependencies": {
39
+ "@formatjs/cli": "^5.1.7",
40
+ "@ttoss/config": "^1.21.0",
41
+ "@ttoss/test-utils": "^1.18.1"
42
+ },
43
+ "keywords": [
44
+ "React",
45
+ "ui",
46
+ "user interface"
47
+ ],
48
+ "publishConfig": {
49
+ "access": "public"
50
+ },
51
+ "gitHead": "9fa7581b00cd6971aa59e3a684c9372b27c35ca9"
52
+ }
@@ -0,0 +1,73 @@
1
+ import * as React from 'react';
2
+ import { IntlProvider } from 'react-intl';
3
+
4
+ export type MessagesType = any;
5
+
6
+ // eslint-disable-next-line no-unused-vars
7
+ export type LoadLocaleData = (locale: string) => Promise<MessagesType>;
8
+
9
+ export type I18nProviderProps = {
10
+ locale?: string;
11
+ loadLocaleData?: LoadLocaleData;
12
+ children?: React.ReactNode;
13
+ };
14
+
15
+ /**
16
+ * `DEFAULT_LOCALE` must be `en` because is the default of the other modules.
17
+ */
18
+ export const DEFAULT_LOCALE = 'en';
19
+
20
+ export type I18nConfigContextProps = Omit<
21
+ I18nProviderProps,
22
+ 'LoadLocaleData'
23
+ > & {
24
+ defaultLocale: string;
25
+ // eslint-disable-next-line no-unused-vars
26
+ setLocale: (language: string) => void;
27
+ };
28
+
29
+ export const I18nConfigContext = React.createContext<I18nConfigContextProps>({
30
+ defaultLocale: DEFAULT_LOCALE,
31
+ setLocale: () => {
32
+ return null;
33
+ },
34
+ });
35
+
36
+ export const I18nProvider = ({
37
+ children,
38
+ locale: initialLocale,
39
+ loadLocaleData,
40
+ ...intlConfig
41
+ }: I18nProviderProps) => {
42
+ const [locale, setLocale] = React.useState(initialLocale || DEFAULT_LOCALE);
43
+
44
+ const [messages, setMessages] = React.useState<MessagesType>();
45
+
46
+ React.useEffect(() => {
47
+ if (loadLocaleData) {
48
+ loadLocaleData(locale).then((message) => {
49
+ return setMessages(message);
50
+ });
51
+ }
52
+ }, [loadLocaleData, locale]);
53
+
54
+ return (
55
+ <I18nConfigContext.Provider
56
+ value={{
57
+ defaultLocale: DEFAULT_LOCALE,
58
+ locale,
59
+ setLocale,
60
+ ...intlConfig,
61
+ }}
62
+ >
63
+ <IntlProvider
64
+ defaultLocale={DEFAULT_LOCALE}
65
+ locale={locale}
66
+ messages={messages}
67
+ {...intlConfig}
68
+ >
69
+ <>{children}</>
70
+ </IntlProvider>
71
+ </I18nConfigContext.Provider>
72
+ );
73
+ };
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export { defineMessages, defineMessage, FormattedMessage } from 'react-intl';
2
+ export {
3
+ I18nProvider,
4
+ I18nProviderProps,
5
+ LoadLocaleData,
6
+ DEFAULT_LOCALE,
7
+ } from './i18Provider';
8
+ export { useI18n } from './useI18n';
package/src/useI18n.ts ADDED
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ import { I18nConfigContext } from './i18Provider';
3
+ import { useIntl } from 'react-intl';
4
+
5
+ export const useI18n = () => {
6
+ const intl = useIntl();
7
+
8
+ const config = React.useContext(I18nConfigContext);
9
+
10
+ return { ...config, intl };
11
+ };