├── .github ├── ISSUE_TEMPLATE │ ├── 01_bug_report.yml │ ├── 02_feature_request.yml │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md ├── codecov.yml ├── verdaccio │ ├── .yarnrc.yml │ └── config.yaml └── workflows │ ├── docs-suite.yml │ ├── lint-pr-title.yml │ ├── main-suite.yml │ ├── next-sync.yml │ ├── release-docs.yml │ ├── release-test.yml │ ├── release.yml │ └── size-limit.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc.json ├── .yarn ├── plugins │ └── @yarnpkg │ │ └── plugin-workspace-tools.cjs └── releases │ └── yarn-3.4.1.cjs ├── .yarnrc.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── babel.config.js ├── eslint.config.mjs ├── examples ├── create-react-app │ ├── .babelrc │ ├── .env │ ├── .gitignore │ ├── README.md │ ├── lingui.config.js │ ├── package.json │ ├── public │ │ └── index.html │ ├── src │ │ ├── App.css │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── i18n.ts │ │ ├── index.css │ │ ├── index.tsx │ │ ├── locales │ │ │ ├── cs.po │ │ │ └── en.po │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── serviceWorker.ts │ │ └── setupTests.ts │ ├── tsconfig.json │ └── yarn.lock ├── js │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── lingui.config.js │ ├── package.json │ ├── src │ │ ├── ids.js │ │ ├── locale │ │ │ ├── cs │ │ │ │ ├── messages.js │ │ │ │ └── messages.po │ │ │ └── en │ │ │ │ ├── messages.js │ │ │ │ └── messages.po │ │ ├── messages.js │ │ └── test.js │ └── yarn.lock ├── nextjs-babel │ ├── .babelrc │ ├── .gitignore │ ├── README.md │ ├── lingui.config.js │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── vercel.svg │ ├── src │ │ ├── components │ │ │ ├── Layout.module.css │ │ │ ├── Layout.tsx │ │ │ └── PluralExample.tsx │ │ ├── i18n.ts │ │ ├── locales │ │ │ ├── cs.po │ │ │ ├── en.po │ │ │ └── pseudo.po │ │ ├── pages │ │ │ ├── _app.tsx │ │ │ ├── api │ │ │ │ └── hello.ts │ │ │ ├── examples.tsx │ │ │ ├── index.module.css │ │ │ └── index.tsx │ │ └── styles.css │ ├── tsconfig.json │ └── yarn.lock ├── nextjs-swc │ ├── .eslintrc.json │ ├── .gitignore │ ├── .prettierrc.js │ ├── README.md │ ├── lingui.config.js │ ├── next-env.d.ts │ ├── next.config.ts │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── vercel.svg │ ├── src │ │ ├── app │ │ │ └── [lang] │ │ │ │ ├── app-router-demo │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ ├── appRouterI18n.ts │ │ ├── components │ │ │ ├── AboutText.tsx │ │ │ ├── Developers.tsx │ │ │ ├── HomePage.tsx │ │ │ ├── LinguiClientProvider.tsx │ │ │ └── Switcher.tsx │ │ ├── initLingui.tsx │ │ ├── locales │ │ │ ├── en.po │ │ │ ├── es.po │ │ │ ├── pseudo.po │ │ │ └── sr.po │ │ ├── middleware.ts │ │ ├── pages │ │ │ ├── [lang] │ │ │ │ └── pages-router-demo │ │ │ │ │ └── index.tsx │ │ │ └── _app.tsx │ │ ├── pagesRouterI18n.ts │ │ └── styles │ │ │ ├── Index.module.css │ │ │ └── globals.css │ ├── tsconfig.json │ └── yarn.lock ├── react-native │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── .yarnrc.yml │ ├── App.tsx │ ├── README.md │ ├── app.json │ ├── assets │ │ ├── adaptive-icon.png │ │ ├── favicon.png │ │ ├── icon.png │ │ └── splash.png │ ├── babel.config.js │ ├── lingui.config.js │ ├── metro.config.js │ ├── package.json │ ├── src │ │ ├── Components.tsx │ │ ├── MainScreen.tsx │ │ ├── PaddedButton.tsx │ │ ├── locales │ │ │ ├── cs │ │ │ │ └── messages.po │ │ │ └── en │ │ │ │ └── messages.po │ │ └── po-types.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── remix-vite-babel │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── entry.client.tsx │ │ ├── entry.server.tsx │ │ ├── locales │ │ │ ├── en.po │ │ │ └── fr.po │ │ ├── modules │ │ │ └── lingui │ │ │ │ ├── config.ts │ │ │ │ ├── lingui.server.ts │ │ │ │ ├── lingui.tsx │ │ │ │ ├── remix.server.ts │ │ │ │ └── utils.ts │ │ ├── root.tsx │ │ └── routes │ │ │ └── _index.tsx │ ├── lingui.config.ts │ ├── package.json │ ├── tsconfig.json │ ├── vite.config.ts │ └── yarn.lock ├── rspack │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── demo.gif │ ├── index.html │ ├── lingui.config.ts │ ├── package.json │ ├── rspack.config.js │ ├── src │ │ ├── Inbox.tsx │ │ ├── LocaleSwitcher.tsx │ │ ├── assets │ │ │ └── react.svg │ │ ├── index.css │ │ ├── locales.ts │ │ ├── locales │ │ │ ├── en │ │ │ │ ├── messages.d.ts │ │ │ │ ├── messages.po │ │ │ │ └── messages.ts │ │ │ └── fr │ │ │ │ ├── messages.d.ts │ │ │ │ ├── messages.po │ │ │ │ └── messages.ts │ │ ├── main.tsx │ │ └── react-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── tanstack-start │ ├── .gitignore │ ├── .prettierignore │ ├── README.md │ ├── app.config.ts │ ├── lingui.config.ts │ ├── package.json │ ├── postcss.config.mjs │ ├── public │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── favicon.png │ │ └── site.webmanifest │ ├── src │ │ ├── api.ts │ │ ├── client.tsx │ │ ├── components │ │ │ ├── DefaultCatchBoundary.tsx │ │ │ ├── NotFound.tsx │ │ │ ├── PostError.tsx │ │ │ └── UserError.tsx │ │ ├── functions │ │ │ └── deferred.ts │ │ ├── global-middleware.ts │ │ ├── locales │ │ │ ├── en │ │ │ │ └── messages.po │ │ │ └── fr │ │ │ │ └── messages.po │ │ ├── modules │ │ │ └── lingui │ │ │ │ ├── i18n.server.ts │ │ │ │ └── i18n.ts │ │ ├── routeTree.gen.ts │ │ ├── router.tsx │ │ ├── routes │ │ │ ├── __root.tsx │ │ │ ├── _pathlessLayout.tsx │ │ │ ├── _pathlessLayout │ │ │ │ ├── _nested-layout.tsx │ │ │ │ └── _nested-layout │ │ │ │ │ ├── route-a.tsx │ │ │ │ │ └── route-b.tsx │ │ │ ├── api │ │ │ │ ├── users.$id.ts │ │ │ │ └── users.ts │ │ │ ├── deferred.tsx │ │ │ ├── index.tsx │ │ │ ├── posts.$postId.tsx │ │ │ ├── posts.index.tsx │ │ │ ├── posts.route.tsx │ │ │ ├── posts_.$postId.deep.tsx │ │ │ ├── redirect.tsx │ │ │ ├── users.$userId.tsx │ │ │ ├── users.index.tsx │ │ │ └── users.route.tsx │ │ ├── ssr.tsx │ │ ├── styles │ │ │ └── app.css │ │ └── utils │ │ │ ├── loggingMiddleware.tsx │ │ │ ├── posts.tsx │ │ │ ├── seo.ts │ │ │ └── users.tsx │ ├── tailwind.config.mjs │ ├── tsconfig.json │ └── yarn.lock ├── vite-project-react-babel │ ├── .gitignore │ ├── index.html │ ├── lingui.config.ts │ ├── package.json │ ├── public │ │ └── vite.svg │ ├── src │ │ ├── App.css │ │ ├── App.tsx │ │ ├── assets │ │ │ ├── lingui-logo.svg │ │ │ └── react.svg │ │ ├── i18n.ts │ │ ├── index.css │ │ ├── locales │ │ │ ├── en.po │ │ │ └── pl.po │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ ├── vite.config.ts │ └── yarn.lock └── vite-project-react-swc │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── lingui.config.ts │ ├── package.json │ ├── public │ └── vite.svg │ ├── src │ ├── App.css │ ├── App.tsx │ ├── assets │ │ ├── lingui-logo.svg │ │ └── react.svg │ ├── i18n.ts │ ├── index.css │ ├── locales │ │ ├── en.po │ │ └── pl.po │ ├── main.tsx │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ ├── vite.config.ts │ └── yarn.lock ├── jest.config.js ├── lerna.json ├── package.json ├── packages ├── babel-plugin-extract-messages │ ├── CHANGELOG.md │ ├── README.md │ ├── build.config.ts │ ├── package.json │ ├── src │ │ └── index.ts │ ├── test │ │ ├── __snapshots__ │ │ │ └── index.ts.snap │ │ ├── fixtures │ │ │ ├── js-call-expression.js │ │ │ ├── js-message-descriptor.js │ │ │ ├── js-with-macros.js │ │ │ ├── jsx-with-macros.js │ │ │ ├── jsx-without-macros.js │ │ │ ├── jsx-without-trans.js │ │ │ ├── lingui.config.js │ │ │ └── without-lingui.js │ │ └── index.ts │ └── tsconfig.json ├── babel-plugin-lingui-macro │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── ast.ts │ │ ├── constants.ts │ │ ├── icu.test.ts │ │ ├── icu.ts │ │ ├── index.ts │ │ ├── macro.ts │ │ ├── macroJs.ts │ │ ├── macroJsAst.test.ts │ │ ├── macroJsAst.ts │ │ ├── macroJsx.test.ts │ │ ├── macroJsx.ts │ │ ├── messageDescriptorUtils.ts │ │ ├── utils.ts │ │ └── utils │ │ │ └── cleanJSXElementLiteralChild.ts │ ├── test │ │ ├── __snapshots__ │ │ │ ├── js-defineMessage.test.ts.snap │ │ │ ├── js-plural.test.ts.snap │ │ │ ├── js-select.test.ts.snap │ │ │ ├── js-selectOrdinal.test.ts.snap │ │ │ ├── js-t.test.ts.snap │ │ │ ├── js-useLingui.test.ts.snap │ │ │ ├── jsx-plural.test.ts.snap │ │ │ ├── jsx-select.test.ts.snap │ │ │ ├── jsx-selectOrdinal.test.ts.snap │ │ │ └── jsx-trans.test.ts.snap │ │ ├── fixtures │ │ │ ├── js-t-continuation-character.expected.js │ │ │ ├── js-t-continuation-character.js │ │ │ ├── js-t-var │ │ │ │ ├── js-t-var.expected.js │ │ │ │ └── js-t-var.js │ │ │ ├── jsx-keep-forced-newlines.expected.js │ │ │ ├── jsx-keep-forced-newlines.js │ │ │ ├── jsx-plural-select-nested.expected.js │ │ │ └── jsx-plural-select-nested.js │ │ ├── index.ts │ │ ├── js-defineMessage.test.ts │ │ ├── js-plural.test.ts │ │ ├── js-select.test.ts │ │ ├── js-selectOrdinal.test.ts │ │ ├── js-t.test.ts │ │ ├── js-useLingui.test.ts │ │ ├── jsx-plural.test.ts │ │ ├── jsx-select.test.ts │ │ ├── jsx-selectOrdinal.test.ts │ │ ├── jsx-trans.test.ts │ │ ├── lingui.config.js │ │ └── macroTester.ts │ └── tsconfig.json ├── cli │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── api.ts │ ├── package.json │ ├── src │ │ ├── api │ │ │ ├── __snapshots__ │ │ │ │ ├── catalog.test.ts.snap │ │ │ │ └── compile.test.ts.snap │ │ │ ├── catalog.test.ts │ │ │ ├── catalog.ts │ │ │ ├── catalog │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── getCatalogs.test.ts.snap │ │ │ │ ├── extractFromFiles.ts │ │ │ │ ├── getCatalogDependentFiles.test.ts │ │ │ │ ├── getCatalogDependentFiles.ts │ │ │ │ ├── getCatalogs.test.ts │ │ │ │ ├── getCatalogs.ts │ │ │ │ ├── getFallbackListForLocale.test.ts │ │ │ │ ├── getFallbackListForLocale.ts │ │ │ │ ├── getTranslationsForCatalog.test.ts │ │ │ │ ├── getTranslationsForCatalog.ts │ │ │ │ ├── mergeCatalog.test.ts │ │ │ │ └── mergeCatalog.ts │ │ │ ├── compile.test.ts │ │ │ ├── compile.ts │ │ │ ├── extractors │ │ │ │ ├── babel.ts │ │ │ │ ├── index.ts │ │ │ │ └── typescript.ts │ │ │ ├── fixtures │ │ │ │ ├── .linguirc │ │ │ │ ├── collect-inline-sourcemaps │ │ │ │ │ └── componentB.jsx │ │ │ │ ├── collect-invalid │ │ │ │ │ ├── invalid.js │ │ │ │ │ └── valid.js │ │ │ │ ├── collect-syntax-flow │ │ │ │ │ ├── flow-syntax.js │ │ │ │ │ └── ts-syntax.ts │ │ │ │ ├── collect-typescript-jsx │ │ │ │ │ ├── jsx-in-js.js │ │ │ │ │ ├── jsx-syntax.jsx │ │ │ │ │ ├── macro.tsx │ │ │ │ │ ├── tsx-experimental-decorators.tsx │ │ │ │ │ └── tsx-syntax.tsx │ │ │ │ ├── collect │ │ │ │ │ ├── $componentE │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── (componentC) │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── [componentD] │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── componentA │ │ │ │ │ │ ├── componentA.js │ │ │ │ │ │ └── index.js │ │ │ │ │ └── componentB.js │ │ │ │ ├── duplicate-id.js │ │ │ │ ├── locales │ │ │ │ │ └── existing │ │ │ │ │ │ ├── cs.po │ │ │ │ │ │ └── en.po │ │ │ │ ├── messages.po │ │ │ │ ├── pot-template │ │ │ │ │ ├── messages.pot │ │ │ │ │ └── pl.po │ │ │ │ └── readAll │ │ │ │ │ ├── cs │ │ │ │ │ └── messages.po │ │ │ │ │ └── en │ │ │ │ │ └── messages.po │ │ │ ├── formats │ │ │ │ ├── formatterWrapper.test.ts │ │ │ │ ├── formatterWrapper.ts │ │ │ │ └── index.ts │ │ │ ├── help.ts │ │ │ ├── index.ts │ │ │ ├── messages.test.ts │ │ │ ├── messages.ts │ │ │ ├── pseudoLocalize.test.ts │ │ │ ├── pseudoLocalize.ts │ │ │ ├── rethrownError.ts │ │ │ ├── stats.test.ts │ │ │ ├── stats.ts │ │ │ ├── types.ts │ │ │ ├── utils.test.ts │ │ │ └── utils.ts │ │ ├── extract-experimental │ │ │ ├── bundleSource.ts │ │ │ ├── constants.ts │ │ │ ├── getEntryPoints.ts │ │ │ ├── getExperimentalCatalogs.ts │ │ │ ├── linguiEsbuildPlugin.ts │ │ │ ├── resolveCatalogPath.ts │ │ │ ├── resolveTemplatePath.test.ts │ │ │ ├── resolveTemplatePath.ts │ │ │ └── writeCatalogs.ts │ │ ├── index.ts │ │ ├── lingui-compile.ts │ │ ├── lingui-extract-experimental.ts │ │ ├── lingui-extract-template.ts │ │ ├── lingui-extract.ts │ │ ├── lingui.ts │ │ ├── services │ │ │ └── translationIO.ts │ │ ├── test │ │ │ ├── __snapshots__ │ │ │ │ └── compile.test.ts.snap │ │ │ └── compile.test.ts │ │ └── tests.ts │ ├── test │ │ ├── .gitignore │ │ ├── extract-partial-consistency │ │ │ ├── existing │ │ │ │ └── en.po │ │ │ ├── expected │ │ │ │ └── en.po │ │ │ └── fixtures │ │ │ │ ├── file-a.ts │ │ │ │ └── file-b.tsx │ │ ├── extract-po-format │ │ │ ├── expected │ │ │ │ ├── en.po │ │ │ │ └── pl.po │ │ │ └── fixtures │ │ │ │ ├── file-a.ts │ │ │ │ ├── file-b.tsx │ │ │ │ └── placeholders.ts │ │ ├── extract-template-po-format │ │ │ ├── expected │ │ │ │ └── messages.pot │ │ │ └── fixtures │ │ │ │ ├── file-a.ts │ │ │ │ └── file-b.tsx │ │ ├── extractor-experimental-clean │ │ │ ├── existing │ │ │ │ ├── about.page.en.po │ │ │ │ ├── about.page.pl.po │ │ │ │ ├── index.page.en.po │ │ │ │ └── index.page.pl.po │ │ │ ├── expected │ │ │ │ ├── about.page.en.po │ │ │ │ ├── about.page.pl.po │ │ │ │ ├── index.page.en.po │ │ │ │ └── index.page.pl.po │ │ │ ├── fixtures │ │ │ │ ├── components │ │ │ │ │ └── header.ts │ │ │ │ └── pages │ │ │ │ │ ├── about.page.ts │ │ │ │ │ └── index.page.ts │ │ │ └── package.json │ │ ├── extractor-experimental-template │ │ │ ├── expected │ │ │ │ ├── about.page.en.js │ │ │ │ ├── about.page.messages.pot │ │ │ │ ├── about.page.pl.js │ │ │ │ ├── index.page.en.js │ │ │ │ ├── index.page.messages.pot │ │ │ │ └── index.page.pl.js │ │ │ ├── fixtures │ │ │ │ ├── components │ │ │ │ │ ├── aliased-module.ts │ │ │ │ │ └── header.ts │ │ │ │ └── pages │ │ │ │ │ ├── about.page.tsx │ │ │ │ │ └── index.page.ts │ │ │ ├── package.json │ │ │ └── tsconfig.json │ │ ├── extractor-experimental │ │ │ ├── existing │ │ │ │ ├── about.page.en.po │ │ │ │ ├── about.page.pl.po │ │ │ │ ├── index.page.en.po │ │ │ │ └── index.page.pl.po │ │ │ ├── expected │ │ │ │ ├── about.page.en.js │ │ │ │ ├── about.page.en.po │ │ │ │ ├── about.page.pl.js │ │ │ │ ├── about.page.pl.po │ │ │ │ ├── index.page.en.js │ │ │ │ ├── index.page.en.po │ │ │ │ ├── index.page.pl.js │ │ │ │ └── index.page.pl.po │ │ │ ├── fixtures │ │ │ │ ├── components │ │ │ │ │ └── header.ts │ │ │ │ ├── constants │ │ │ │ │ ├── green.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── red.ts │ │ │ │ └── pages │ │ │ │ │ ├── about.page.ts │ │ │ │ │ └── index.page.ts │ │ │ └── package.json │ │ └── index.test.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── conf │ ├── CHANGELOG.md │ ├── README.md │ ├── __typetests__ │ │ ├── index.test-d.tsx │ │ └── tsconfig.json │ ├── package.json │ ├── src │ │ ├── __snapshots__ │ │ │ └── index.test.ts.snap │ │ ├── defineConfig.ts │ │ ├── fixtures │ │ │ └── valid │ │ │ │ ├── .linguirc │ │ │ │ ├── custom.config.js │ │ │ │ └── custom.config.ts │ │ ├── getConfig.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── makeConfig.ts │ │ ├── migrations │ │ │ ├── normalizeRuntimeConfigModule.test.ts │ │ │ ├── normalizeRuntimeConfigModule.ts │ │ │ └── setCldrParentLocales.ts │ │ ├── types.ts │ │ └── utils │ │ │ ├── pathJoinPosix.ts │ │ │ ├── replaceRootDir.test.ts │ │ │ └── replaceRootDir.ts │ └── tsconfig.json ├── core │ ├── CHANGELOG.md │ ├── README.md │ ├── __typetests__ │ │ ├── index.test-d.tsx │ │ └── tsconfig.json │ ├── macro │ │ ├── __typetests__ │ │ │ ├── index.test-d.tsx │ │ │ └── tsconfig.json │ │ ├── index.d.ts │ │ ├── index.js │ │ └── index.test.ts │ ├── package.json │ ├── src │ │ ├── essentials.test.ts │ │ ├── essentials.ts │ │ ├── eventEmitter.test.ts │ │ ├── eventEmitter.ts │ │ ├── formats.test.ts │ │ ├── formats.ts │ │ ├── i18n.test.ts │ │ ├── i18n.ts │ │ ├── index.ts │ │ ├── interpolate.test.ts │ │ └── interpolate.ts │ └── tsconfig.json ├── detect-locale │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ └── src │ │ ├── detectors │ │ ├── __snapshots__ │ │ │ └── fromUrl.test.ts.snap │ │ ├── fromCookie.test.ts │ │ ├── fromCookie.ts │ │ ├── fromHtmlTag.test.ts │ │ ├── fromHtmlTag.ts │ │ ├── fromNavigator.test.ts │ │ ├── fromNavigator.ts │ │ ├── fromPath.test.ts │ │ ├── fromPath.ts │ │ ├── fromStorage.test.ts │ │ ├── fromStorage.ts │ │ ├── fromSubdomain.test.ts │ │ ├── fromSubdomain.ts │ │ ├── fromUrl.test.ts │ │ └── fromUrl.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ └── utils │ │ ├── cookie-getter.test.ts │ │ ├── cookie-getter.ts │ │ ├── query-string.test.ts │ │ └── query-string.ts ├── extractor-vue │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ └── src │ │ ├── __snapshots__ │ │ └── extractor.test.ts.snap │ │ ├── extractor.test.ts │ │ ├── fixtures │ │ ├── functional.vue │ │ └── test.vue │ │ ├── index.ts │ │ └── vue-extractor.ts ├── format-csv │ ├── CHANGELOG.md │ ├── README.md │ ├── __typetests__ │ │ ├── index.test-d.ts │ │ └── tsconfig.json │ ├── package.json │ └── src │ │ ├── __snapshots__ │ │ └── csv.test.ts.snap │ │ ├── csv.test.ts │ │ ├── csv.ts │ │ └── fixtures │ │ └── messages.csv ├── format-json │ ├── CHANGELOG.md │ ├── README.md │ ├── __typetests__ │ │ ├── index.test-d.ts │ │ └── tsconfig.json │ ├── package.json │ └── src │ │ ├── __snapshots__ │ │ └── json.test.ts.snap │ │ ├── fixtures │ │ └── messages.json │ │ ├── json.test.ts │ │ └── json.ts ├── format-po-gettext │ ├── CHANGELOG.md │ ├── README.md │ ├── __typetests__ │ │ ├── index.test-d.ts │ │ └── tsconfig.json │ ├── package.json │ └── src │ │ ├── __snapshots__ │ │ └── po-gettext.test.ts.snap │ │ ├── fixtures │ │ ├── messages_plural-4-letter.po │ │ └── messages_plural.po │ │ ├── plural-samples.test.ts │ │ ├── plural-samples.ts │ │ ├── po-gettext.test.ts │ │ └── po-gettext.ts ├── format-po │ ├── CHANGELOG.md │ ├── README.md │ ├── __typetests__ │ │ ├── index.test-d.ts │ │ └── tsconfig.json │ ├── package.json │ └── src │ │ ├── __snapshots__ │ │ ├── po.test.ts.snap │ │ └── utils.test.ts.snap │ │ ├── fixtures │ │ └── messages.po │ │ ├── po.test.ts │ │ ├── po.ts │ │ ├── utils.test.ts │ │ └── utils.ts ├── jest-mocks │ ├── index.test.ts │ ├── index.ts │ └── package.json ├── loader │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── webpackLoader.ts │ └── test │ │ ├── __snapshots__ │ │ └── loader.test.ts.snap │ │ ├── compiler.ts │ │ ├── entrypoint.js │ │ ├── fail-on-compile-errors │ │ ├── entrypoint.js │ │ ├── lingui.config.js │ │ └── locale │ │ │ └── en.po │ │ ├── fail-on-missing-pseudo │ │ ├── entrypoint.js │ │ ├── lingui.config.js │ │ └── locale │ │ │ ├── en.po │ │ │ └── pseudo.po │ │ ├── fail-on-missing │ │ ├── entrypoint.js │ │ ├── lingui.config.js │ │ └── locale │ │ │ └── en.po │ │ ├── json-format │ │ ├── entrypoint.js │ │ ├── lingui.config.ts │ │ └── locale │ │ │ └── en.json │ │ ├── loader.test.ts │ │ ├── not-known-catalog │ │ ├── .linguirc │ │ ├── entrypoint.js │ │ └── locale │ │ │ └── en.po │ │ ├── po-format │ │ ├── .linguirc │ │ ├── entrypoint.js │ │ └── locale │ │ │ ├── en.po │ │ │ └── messages.pot │ │ └── relative-catalog-path │ │ ├── .linguirc │ │ ├── entrypoint.js │ │ └── locale │ │ ├── en.po │ │ └── messages.pot ├── macro │ ├── CHANGELOG.md │ ├── README.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── message-utils │ ├── CHANGELOG.md │ ├── README.md │ ├── build.config.ts │ ├── compileMessage.js │ ├── generateMessageId.js │ ├── package.json │ ├── src │ │ ├── compileMessage.test.ts │ │ ├── compileMessage.ts │ │ ├── generateMessageId.test.ts │ │ └── generateMessageId.ts │ └── tsconfig.json ├── metro-transformer │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── expo │ │ │ └── index.ts │ │ ├── metroTransformer.ts │ │ ├── react-native │ │ │ └── index.ts │ │ └── types.ts │ └── test │ │ ├── __fixtures__ │ │ └── test-project │ │ │ ├── lingui.config.js │ │ │ └── locales │ │ │ ├── cs │ │ │ └── messages.po │ │ │ └── en │ │ │ └── messages.po │ │ └── metroTransformer.test.ts ├── react │ ├── .eslintrc │ ├── CHANGELOG.md │ ├── README.md │ ├── build.config.ts │ ├── macro │ │ ├── __typetests__ │ │ │ ├── index.test-d.tsx │ │ │ └── tsconfig.json │ │ ├── index.d.ts │ │ ├── index.js │ │ └── index.test.ts │ ├── package.json │ ├── src │ │ ├── I18nProvider.test.tsx │ │ ├── I18nProvider.tsx │ │ ├── Trans.test.tsx │ │ ├── Trans.tsx │ │ ├── TransNoContext.tsx │ │ ├── TransRsc.tsx │ │ ├── format.test.tsx │ │ ├── format.ts │ │ ├── index-rsc.ts │ │ ├── index.ts │ │ └── server.ts │ └── tsconfig.json ├── remote-loader │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── browserCompiler.ts │ │ ├── index.ts │ │ └── minimalParser.ts │ └── test │ │ └── index.test.ts └── vite-plugin │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ └── index.ts │ ├── test │ ├── __snapshots__ │ │ └── index.ts.snap │ ├── default-vite.config.ts │ ├── fail-on-compile-errors │ │ ├── entrypoint.js │ │ ├── failOnCompileErrorFalse.vite.config.ts │ │ ├── lingui.config.js │ │ ├── locale │ │ │ └── en.po │ │ └── vite.config.ts │ ├── fail-on-missing-pseudo │ │ ├── entrypoint.js │ │ ├── lingui.config.js │ │ ├── locale │ │ │ ├── en.po │ │ │ └── pseudo.po │ │ └── vite.config.ts │ ├── fail-on-missing │ │ ├── entrypoint.js │ │ ├── lingui.config.js │ │ ├── locale │ │ │ └── en.po │ │ └── vite.config.ts │ ├── index.ts │ ├── json-format │ │ ├── entrypoint.js │ │ ├── lingui.config.ts │ │ ├── locale │ │ │ └── en.json │ │ └── vite.config.ts │ ├── macro-usage │ │ ├── .linguirc │ │ ├── entrypoint.js │ │ ├── locale │ │ │ └── en.po │ │ └── vite.config.ts │ ├── no-macro-error │ │ ├── .linguirc │ │ ├── entrypoint.js │ │ ├── locale │ │ │ └── en.po │ │ └── vite.config.ts │ └── po-format │ │ ├── entrypoint.js │ │ ├── lingui.config.js │ │ ├── locale │ │ └── en.po │ │ └── vite.config.ts │ └── tsconfig.json ├── scripts ├── jest │ ├── env.js │ ├── setupTimezone.js │ └── stripAnsiSerializer.js └── verdaccio-release.ts ├── test ├── cli-version │ ├── index.js │ └── package.json ├── node-api-esm │ ├── index.js │ └── package.json ├── node-api │ ├── index.js │ └── package.json └── typescript-nodenext-resolution │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── tsconfig.json ├── tstyche.config.json ├── vercel.json ├── website ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── .remarkrc.mjs ├── babel.config.js ├── blog │ ├── 2023-04-26-announcing-lingui-4.0 │ │ ├── index.md │ │ └── social-card.png │ ├── 2023-12-12-4k-stars │ │ ├── index.md │ │ └── social-card.png │ ├── 2024-11-20-metro-transformer │ │ ├── index.md │ │ └── social-card.png │ ├── 2024-11-28-announcing-lingui-5.0 │ │ ├── index.md │ │ └── social-card.png │ └── authors.yml ├── docs │ ├── community.md │ ├── examples.md │ ├── guides │ │ ├── custom-extractor.md │ │ ├── custom-formatter.md │ │ ├── dynamic-loading-catalogs.md │ │ ├── explicit-vs-generated-ids.md │ │ ├── lazy-translations.md │ │ ├── message-extraction.md │ │ ├── message-format.md │ │ ├── monorepo.md │ │ ├── plurals.md │ │ ├── pseudolocalization.md │ │ └── testing.md │ ├── installation.mdx │ ├── introduction.md │ ├── misc │ │ ├── i18next.md │ │ ├── react-intl.md │ │ ├── resources.md │ │ ├── showroom.md │ │ └── tooling.md │ ├── ref │ │ ├── catalog-formats.md │ │ ├── cli.md │ │ ├── conf.md │ │ ├── core.md │ │ ├── eslint-plugin.md │ │ ├── extractor-vue.md │ │ ├── loader.md │ │ ├── locale-detector.md │ │ ├── macro.mdx │ │ ├── metro-transformer.mdx │ │ ├── react.md │ │ ├── swc-plugin.md │ │ └── vite-plugin.md │ ├── releases │ │ ├── migration-3.md │ │ ├── migration-4.md │ │ └── migration-5.md │ ├── tools │ │ ├── crowdin.md │ │ ├── introduction.md │ │ └── translation-io.md │ └── tutorials │ │ ├── javascript.md │ │ ├── react-native.md │ │ ├── react-rsc.md │ │ └── react.md ├── docusaurus.config.ts ├── eslint.config.mjs ├── linkcheck-ignore.txt ├── package.json ├── sidebars.ts ├── src │ ├── components │ │ ├── Button.tsx │ │ ├── Code.tsx │ │ ├── Features.module.scss │ │ ├── Features.tsx │ │ ├── Header.module.scss │ │ ├── Header.tsx │ │ ├── PartnerBanner.module.scss │ │ ├── PartnerBanner.tsx │ │ ├── Users.module.scss │ │ ├── Users.tsx │ │ └── Workflow.tsx │ ├── css │ │ └── custom.scss │ ├── definitions.d.ts │ ├── pages │ │ └── index.tsx │ └── theme │ │ └── Footer │ │ └── index.js ├── static │ ├── .nojekyll │ └── img │ │ ├── docs │ │ ├── Crowdin__js-lingui-vcs.png │ │ ├── dynamic-loading-catalogs-1.png │ │ ├── dynamic-loading-catalogs-2.png │ │ ├── extractor-deps-scheme.svg │ │ ├── extractor-glob-scheme.svg │ │ ├── lingui-workflow.svg │ │ ├── rn-component-nesting.png │ │ ├── translation-lingui-plural-forms.png │ │ ├── with-collaboration-tool.svg │ │ └── without-collaboration-tool.svg │ │ ├── favicon.ico │ │ ├── features │ │ ├── ai-ready.png │ │ ├── all-platforms.svg │ │ ├── clean-and-readable.png │ │ ├── fledged.svg │ │ ├── pattern-left-big.svg │ │ ├── pattern-right-big.svg │ │ ├── rich-text.svg │ │ ├── time.svg │ │ ├── tooling.png │ │ ├── universal.svg │ │ └── verified.svg │ │ ├── header │ │ ├── left-bg.svg │ │ └── right-bg.svg │ │ ├── lingui-logo.svg │ │ ├── logo-small.svg │ │ ├── og-image-examples.png │ │ ├── og-image.png │ │ └── users │ │ ├── ansible.png │ │ ├── bluesky.png │ │ ├── brave.png │ │ ├── documenso.png │ │ ├── fider.png │ │ ├── flood.svg │ │ ├── graysky.png │ │ ├── linkerd.png │ │ ├── metamask.png │ │ ├── remirror.png │ │ ├── twenty.png │ │ └── zipkin.png ├── tools │ └── algolia │ │ └── config.json ├── tsconfig.json └── yarn.lock └── yarn.lock /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: View documentation 4 | url: https://lingui.dev 5 | about: Check the official docs for answers to common questions 6 | - name: Chat on Discord 7 | url: https://discord.gg/gFWwAYnMtA 8 | about: Join the Lingui community on Discord 9 | - name: Ask AI 10 | url: https://gurubase.io/g/lingui-js 11 | about: Ask Lingui JS Guru - AI powered Q&A assistant 12 | -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | # https://docs.codecov.com/docs/codecovyml-reference 2 | 3 | codecov: 4 | notify: 5 | require_ci_to_pass: yes 6 | 7 | coverage: 8 | precision: 2 9 | round: down 10 | range: "65...100" 11 | 12 | status: 13 | project: 14 | default: 15 | target: auto 16 | threshold: 2% 17 | patch: 18 | default: 19 | target: 70% 20 | -------------------------------------------------------------------------------- /.github/verdaccio/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | npmScopes: 2 | lingui: 3 | npmRegistryServer: http://0.0.0.0:4873/ 4 | npmPublishRegistry: http://0.0.0.0:4873/ 5 | 6 | unsafeHttpWhitelist: 7 | - 0.0.0.0 8 | -------------------------------------------------------------------------------- /.github/verdaccio/config.yaml: -------------------------------------------------------------------------------- 1 | listen: 0.0.0.0:4873 2 | auth: 3 | auth-memory: 4 | users: 5 | foo: 6 | name: test 7 | password: test 8 | store: 9 | memory: 10 | limit: 1000 11 | uplinks: 12 | npmjs: 13 | url: https://registry.npmjs.org/ 14 | packages: 15 | '@*/*': 16 | access: $all 17 | publish: $all 18 | '**': 19 | access: $all 20 | publish: $all 21 | middlewares: 22 | audit: 23 | enabled: true 24 | log: 25 | - {type: stdout, format: pretty, level: trace} 26 | -------------------------------------------------------------------------------- /.github/workflows/docs-suite.yml: -------------------------------------------------------------------------------- 1 | name: docs-suite 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - '*' 7 | paths: 8 | - website/** 9 | 10 | jobs: 11 | validate: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Setup node 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version: 'lts/*' 21 | 22 | - name: Install dependencies 23 | working-directory: website 24 | run: yarn install 25 | 26 | - name: Build 27 | working-directory: website 28 | run: yarn build 29 | 30 | - name: Lint 31 | working-directory: website 32 | run: yarn lint 33 | 34 | - name: Check Formatting 35 | working-directory: website 36 | run: yarn checkFormat 37 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr-title.yml: -------------------------------------------------------------------------------- 1 | name: lint-pr-title 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - reopened 8 | - edited 9 | - synchronize 10 | 11 | jobs: 12 | main: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: amannn/action-semantic-pull-request@v5 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | -------------------------------------------------------------------------------- /.github/workflows/next-sync.yml: -------------------------------------------------------------------------------- 1 | name: next-sync 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | next-sync: 10 | runs-on: ubuntu-latest 11 | name: Syncing branches 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | 17 | - name: Set up Node 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version: 'lts/*' 21 | 22 | - name: Opening pull request 23 | id: pull 24 | uses: tretuna/sync-branches@1.4.0 25 | with: 26 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 27 | FROM_BRANCH: "main" 28 | TO_BRANCH: "next" 29 | PULL_REQUEST_TITLE: "chore: sync main to next" 30 | -------------------------------------------------------------------------------- /.github/workflows/size-limit.yml: -------------------------------------------------------------------------------- 1 | name: Size Testing 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - synchronize 8 | - reopened 9 | 10 | jobs: 11 | size: 12 | runs-on: ubuntu-latest 13 | env: 14 | CI_JOB_NUMBER: 1 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - uses: andresz1/size-limit-action@v1.8.0 20 | with: 21 | build_script: release:build 22 | github_token: ${{ secrets.GITHUB_TOKEN }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .yalc/ 3 | yalc.lock 4 | dist 5 | 6 | npm-debug.log 7 | yarn-error.log 8 | 9 | coverage/ 10 | results/ 11 | junit.xml 12 | 13 | .DS_Store 14 | .vscode 15 | .idea 16 | *.iml 17 | 18 | .pnp.* 19 | .yarn/* 20 | !.yarn/patches 21 | !.yarn/plugins 22 | !.yarn/releases 23 | !.yarn/sdks 24 | !.yarn/versions 25 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/.next/* 2 | **/dist/* 3 | **/test/fixtures/** 4 | **/test/**/actual.js 5 | **/test/**/actual/** 6 | **/test/**/expected.js 7 | **/locale/* 8 | **/fixtures/* 9 | **/expected/* 10 | coverage/ 11 | website/ 12 | .github 13 | examples 14 | /.nx/workspace-data 15 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false 3 | } 4 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | plugins: 4 | - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs 5 | spec: "@yarnpkg/plugin-workspace-tools" 6 | 7 | yarnPath: .yarn/releases/yarn-3.4.1.cjs 8 | 9 | unsafeHttpWhitelist: 10 | - 0.0.0.0 11 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: 16, 8 | }, 9 | modules: "commonjs", 10 | }, 11 | ], 12 | "@babel/preset-typescript", 13 | "@babel/preset-react", 14 | ], 15 | } 16 | -------------------------------------------------------------------------------- /examples/create-react-app/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "next/babel" 4 | ], 5 | "plugins": ["@lingui/babel-plugin-lingui-macro"] 6 | } 7 | -------------------------------------------------------------------------------- /examples/create-react-app/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true -------------------------------------------------------------------------------- /examples/create-react-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | .pnp.* 26 | .yarn/* 27 | !.yarn/patches 28 | !.yarn/plugins 29 | !.yarn/releases 30 | !.yarn/sdks 31 | !.yarn/versions 32 | -------------------------------------------------------------------------------- /examples/create-react-app/lingui.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@lingui/conf').LinguiConfig} */ 2 | module.exports = { 3 | locales: ["en", "cs"], 4 | sourceLocale: "en", 5 | catalogs: [ 6 | { 7 | path: "/src/locales/{locale}", 8 | include: [""], 9 | exclude: ["**/node_modules/**"], 10 | }, 11 | ], 12 | format: "po", 13 | } 14 | -------------------------------------------------------------------------------- /examples/create-react-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | React App 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/create-react-app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 10vmin; 7 | pointer-events: none; 8 | } 9 | 10 | .App-header { 11 | background-color: #282c34; 12 | min-height: 100vh; 13 | display: flex; 14 | flex-direction: column; 15 | align-items: center; 16 | justify-content: center; 17 | font-size: calc(10px + 2vmin); 18 | color: white; 19 | } 20 | 21 | 22 | .lang-container { 23 | display: flex; 24 | } 25 | 26 | .lang-container button { 27 | margin: 1rem; 28 | background: rgb(164, 13, 13); 29 | color: white; 30 | border-radius: 1rem; 31 | box-shadow: none; 32 | border: 0; 33 | padding: 1rem; 34 | text-transform: uppercase; 35 | cursor: pointer; 36 | } 37 | -------------------------------------------------------------------------------- /examples/create-react-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/create-react-app/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/create-react-app/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /examples/create-react-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /examples/js/.gitignore: -------------------------------------------------------------------------------- 1 | src/locale/_build/ 2 | src/locale/*/*.js 3 | 4 | .pnp.* 5 | .yarn/* 6 | !.yarn/patches 7 | !.yarn/plugins 8 | !.yarn/releases 9 | !.yarn/sdks 10 | !.yarn/versions 11 | -------------------------------------------------------------------------------- /examples/js/README.md: -------------------------------------------------------------------------------- 1 | # Using LinguiJS in VanillaJS projects 2 | 3 | Prepare the example by installing dependencies and compiling message catalogs: 4 | 5 | ```sh 6 | yarn install 7 | yarn lingui compile 8 | ``` 9 | 10 | Now, either run full test suit: 11 | 12 | ```sh 13 | yarn test 14 | ``` 15 | 16 | Or each file individually (you need to have `babel-cli` installed globally): 17 | 18 | ```sh 19 | babel-node src/messages.js 20 | ``` 21 | -------------------------------------------------------------------------------- /examples/js/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@babel/env"], 3 | plugins: ["@lingui/babel-plugin-lingui-macro"], 4 | } 5 | -------------------------------------------------------------------------------- /examples/js/lingui.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@lingui/conf').LinguiConfig} */ 2 | module.exports = { 3 | locales: ["en", "cs"], 4 | format: "po", 5 | catalogs: [ 6 | { 7 | path: "./src/locale/{locale}/messages", 8 | include: ["./src"], 9 | }, 10 | ], 11 | sourceLocale: "en", 12 | } 13 | -------------------------------------------------------------------------------- /examples/js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vanilla-js", 3 | "version": "1.0.0", 4 | "main": "src/index.js", 5 | "license": "MIT", 6 | "author": { 7 | "name": "Tomáš Ehrlich", 8 | "email": "tomas.ehrlich@gmail.com" 9 | }, 10 | "scripts": { 11 | "test": "lingui compile && jest src", 12 | "extract": "lingui extract --clean" 13 | }, 14 | "dependencies": { 15 | "@lingui/core": "^5.0.0-next.3" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.20.12", 19 | "@babel/preset-env": "^7.20.2", 20 | "@lingui/babel-plugin-lingui-macro": "^5.0.0-next.3", 21 | "@lingui/cli": "^5.0.0-next.3", 22 | "jest": "^29.5.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/js/src/locale/cs/messages.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/module.exports={messages:JSON.parse("{\"static\":\"Ukázka @lingui/core\",\"zziTz4\":\"Ukázka @lingui/core\",\"lazy\":[\"Chcete pokračovat? \",[\"yes\"],\"/\",[\"no\"]],\"+GYOc0\":[\"Chcete pokračovat? \",[\"yes\"],\"/\",[\"no\"]],\"variables\":[\"Ahoj \",[\"name\"]],\"OVaF9k\":[\"Ahoj \",[\"name\"]],\"common.no\":\"Ne\",\"1UzENP\":\"Ne\",\"plural\":[[\"value\",\"plural\",{\"one\":[\"#\",\" láhev\"],\"few\":[\"#\",\" láhve\"],\"other\":[\"#\",\" láhví\"]}],\" visí na stěně\"],\"KE/K99\":[[\"value\",\"plural\",{\"one\":[\"#\",\" láhev\"],\"few\":[\"#\",\" láhve\"],\"other\":[\"#\",\" láhví\"]}],\" visí na stěně\"],\"common.yes\":\"Ano\",\"l75CjT\":\"Ano\"}")}; -------------------------------------------------------------------------------- /examples/js/src/locale/en/messages.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/module.exports={messages:JSON.parse("{\"static\":\"@lingui/core example\",\"zziTz4\":\"@lingui/core example\",\"lazy\":[\"Do you want to proceed? \",[\"yes\"],\"/\",[\"no\"]],\"+GYOc0\":[\"Do you want to proceed? \",[\"yes\"],\"/\",[\"no\"]],\"variables\":[\"Hello \",[\"name\"]],\"OVaF9k\":[\"Hello \",[\"name\"]],\"common.no\":\"No\",\"1UzENP\":\"No\",\"plural\":[\"There are \",[\"value\",\"plural\",{\"one\":[\"#\",\" bottle\"],\"other\":[\"#\",\" bottles\"]}],\" hanging on the wall\"],\"KE/K99\":[\"There are \",[\"value\",\"plural\",{\"one\":[\"#\",\" bottle\"],\"other\":[\"#\",\" bottles\"]}],\" hanging on the wall\"],\"common.yes\":\"Yes\",\"l75CjT\":\"Yes\"}")}; -------------------------------------------------------------------------------- /examples/nextjs-babel/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "next/babel" 4 | ], 5 | "plugins": ["@lingui/babel-plugin-lingui-macro"] 6 | } 7 | -------------------------------------------------------------------------------- /examples/nextjs-babel/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # LinguiJS 16 | locale/*/*.js 17 | 18 | # production 19 | /build 20 | 21 | # misc 22 | .DS_Store 23 | *.pem 24 | 25 | # debug 26 | npm-debug.log* 27 | yarn-debug.log* 28 | yarn-error.log* 29 | 30 | # local env files 31 | .env.local 32 | .env.development.local 33 | .env.test.local 34 | .env.production.local 35 | 36 | # vercel 37 | .vercel 38 | 39 | .pnp.* 40 | .yarn/* 41 | !.yarn/patches 42 | !.yarn/plugins 43 | !.yarn/releases 44 | !.yarn/sdks 45 | !.yarn/versions 46 | -------------------------------------------------------------------------------- /examples/nextjs-babel/lingui.config.js: -------------------------------------------------------------------------------- 1 | const nextConfig = require("./next.config") 2 | 3 | /** @type {import('@lingui/conf').LinguiConfig} */ 4 | module.exports = { 5 | locales: nextConfig.i18n.locales, 6 | pseudoLocale: "pseudo", 7 | sourceLocale: nextConfig.i18n.defaultLocale, 8 | fallbackLocales: { 9 | default: "en", 10 | }, 11 | catalogs: [ 12 | { 13 | path: "src/locales/{locale}", 14 | include: ["src/"], 15 | }, 16 | ], 17 | } 18 | -------------------------------------------------------------------------------- /examples/nextjs-babel/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /examples/nextjs-babel/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | module.exports = { 3 | i18n: { 4 | // These are all the locales you want to support in 5 | // your application 6 | locales: ["en", "cs", "pseudo"], 7 | defaultLocale: "en", 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /examples/nextjs-babel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-js-babel", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "extract": "lingui extract", 7 | "dev": "next dev", 8 | "build": "yarn extract && next build", 9 | "start": "next start" 10 | }, 11 | "dependencies": { 12 | "@lingui/core": "^5.0.0-next.2", 13 | "@lingui/react": "^5.0.0-next.2", 14 | "classnames": "^2.3.1", 15 | "next": "13.2.4", 16 | "react": "18.2.0", 17 | "react-dom": "18.2.0" 18 | }, 19 | "devDependencies": { 20 | "@lingui/babel-plugin-lingui-macro": "^5.0.0-next.2", 21 | "@lingui/cli": "^5.0.0-next.2", 22 | "@lingui/loader": "^5.0.0-next.2", 23 | "@types/react": "^18.0.28", 24 | "typescript": "^4.9.5", 25 | "webpack": "^5.76.2" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/nextjs-babel/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/nextjs-babel/public/favicon.ico -------------------------------------------------------------------------------- /examples/nextjs-babel/src/components/Layout.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | min-height: 100vh; 3 | max-width: 960px; 4 | width: 100%; 5 | padding: 0 0.5rem; 6 | margin: 0 auto; 7 | display: flex; 8 | flex-direction: column; 9 | justify-content: center; 10 | align-items: center; 11 | } 12 | 13 | .main { 14 | flex: 1; 15 | } 16 | 17 | .footer { 18 | width: 100%; 19 | height: 100px; 20 | border-top: 1px solid #eaeaea; 21 | display: flex; 22 | justify-content: center; 23 | align-items: center; 24 | } 25 | 26 | .footer img { 27 | margin-left: 0.5rem; 28 | } 29 | 30 | .footer a { 31 | display: flex; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | .logo { 37 | height: 1em; 38 | } 39 | 40 | .link { 41 | border: none; 42 | background: none; 43 | cursor: pointer; 44 | font-size: inherit; 45 | } 46 | -------------------------------------------------------------------------------- /examples/nextjs-babel/src/components/PluralExample.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export function PluralExample({ initialValue = 1, render }) { 4 | const [value, setValue] = React.useState(initialValue) 5 | 6 | return ( 7 |
8 |
{render({ value })}
9 |
10 | setValue(e.target.value as any)} 14 | /> 15 |
16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /examples/nextjs-babel/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { I18nProvider } from "@lingui/react" 2 | import { i18n } from "@lingui/core" 3 | 4 | import "../styles.css" 5 | import { useLinguiInit } from "../i18n" 6 | import { AppProps } from "next/app" 7 | 8 | export default function MyApp({ Component, pageProps }: AppProps) { 9 | useLinguiInit(pageProps.translation) 10 | 11 | return ( 12 | <> 13 | 14 | 15 | 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /examples/nextjs-babel/src/pages/api/hello.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.statusCode = 200 5 | res.json({ name: 'John Doe' }) 6 | } 7 | -------------------------------------------------------------------------------- /examples/nextjs-babel/src/styles.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 7 | } 8 | 9 | a { 10 | color: inherit; 11 | text-decoration: none; 12 | } 13 | 14 | * { 15 | box-sizing: border-box; 16 | } 17 | -------------------------------------------------------------------------------- /examples/nextjs-babel/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": [ 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "allowJs": true, 11 | "skipLibCheck": true, 12 | "strict": false, 13 | "forceConsistentCasingInFileNames": true, 14 | "noEmit": true, 15 | "esModuleInterop": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "jsx": "preserve", 21 | "incremental": true 22 | }, 23 | "include": [ 24 | "next-env.d.ts", 25 | "**/*.ts", 26 | "**/*.tsx" 27 | ], 28 | "exclude": [ 29 | "node_modules" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /examples/nextjs-swc/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/nextjs-swc/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # lingui js 37 | /src/translations/**/*.js 38 | 39 | .pnp.* 40 | .yarn/* 41 | !.yarn/patches 42 | !.yarn/plugins 43 | !.yarn/releases 44 | !.yarn/sdks 45 | !.yarn/versions 46 | -------------------------------------------------------------------------------- /examples/nextjs-swc/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: false, 3 | singleQuote: true, 4 | trailingComma: 'none' 5 | // endOfLine: "lf" 6 | } 7 | -------------------------------------------------------------------------------- /examples/nextjs-swc/lingui.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@lingui/conf').LinguiConfig} */ 2 | module.exports = { 3 | locales: ['en', 'sr', 'es', 'pseudo'], 4 | pseudoLocale: 'pseudo', 5 | sourceLocale: 'en', 6 | fallbackLocales: { 7 | default: 'en' 8 | }, 9 | catalogs: [ 10 | { 11 | path: 'src/locales/{locale}', 12 | include: ['src/'] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /examples/nextjs-swc/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // NOTE: This file should not be edited 6 | // see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. 7 | -------------------------------------------------------------------------------- /examples/nextjs-swc/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from 'next' 2 | 3 | const nextConfig: NextConfig = { 4 | experimental: { 5 | swcPlugins: [['@lingui/swc-plugin', {}]], 6 | turbo: { 7 | rules: { 8 | '*.po': { 9 | loaders: ['@lingui/loader'], 10 | as: '*.js' 11 | } 12 | } 13 | } 14 | }, 15 | webpack: (config) => { 16 | config.module.rules.push({ 17 | test: /\.po$/, 18 | use: { 19 | loader: "@lingui/loader", 20 | }, 21 | }); 22 | 23 | return config; 24 | }, 25 | } 26 | 27 | export default nextConfig 28 | -------------------------------------------------------------------------------- /examples/nextjs-swc/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/nextjs-swc/public/favicon.ico -------------------------------------------------------------------------------- /examples/nextjs-swc/src/app/[lang]/app-router-demo/page.tsx: -------------------------------------------------------------------------------- 1 | import { HomePage } from '../../../components/HomePage' 2 | import {initLingui, PageLangParam} from '../../../initLingui' 3 | 4 | export default async function Page(props: PageLangParam) { 5 | const lang = (await props.params).lang 6 | initLingui(lang) 7 | return 8 | } 9 | -------------------------------------------------------------------------------- /examples/nextjs-swc/src/app/[lang]/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function Index() { 4 | return ( 5 | <> 6 | This is the homepage of the demo app. This page is not localized. You can 7 | go to the App router demo or the{' '} 8 | Pages router demo. 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /examples/nextjs-swc/src/components/AboutText.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from '@lingui/react/macro' 2 | 3 | export function AboutText() { 4 | return ( 5 |

6 | 7 | Next.js is an open-source React front-end development web framework that 8 | enables functionality such as server-side rendering and generating 9 | static websites for React based web applications. It is a 10 | production-ready framework that allows developers to quickly create 11 | static and dynamic JAMstack websites and is used widely by many large 12 | companies. 13 | 14 |

15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /examples/nextjs-swc/src/components/Developers.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | // this is a client component because it uses the `useState` hook 3 | 4 | import { useState } from 'react' 5 | import { Trans, Plural } from '@lingui/react/macro' 6 | 7 | export default function Developers() { 8 | const [selected, setSelected] = useState('1') 9 | return ( 10 |
11 |

12 | Plural Test: How many developers? 13 |

14 |
15 | 22 |

23 | 24 |

25 |
26 |
27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /examples/nextjs-swc/src/components/LinguiClientProvider.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { I18nProvider } from '@lingui/react' 4 | import { type Messages, setupI18n } from '@lingui/core' 5 | import { useState } from 'react' 6 | 7 | type Props = { 8 | children: React.ReactNode 9 | initialLocale: string 10 | initialMessages: Messages 11 | } 12 | 13 | export function LinguiClientProvider({ 14 | children, 15 | initialLocale, 16 | initialMessages 17 | }: Props) { 18 | const [i18n] = useState(() => { 19 | return setupI18n({ 20 | locale: initialLocale, 21 | messages: { [initialLocale]: initialMessages } 22 | }) 23 | }) 24 | return {children} 25 | } 26 | -------------------------------------------------------------------------------- /examples/nextjs-swc/src/initLingui.tsx: -------------------------------------------------------------------------------- 1 | import { getI18nInstance } from './appRouterI18n' 2 | import { setI18n } from '@lingui/react/server' 3 | 4 | export type PageLangParam = { 5 | params: Promise<{ lang: string }> 6 | } 7 | 8 | export function initLingui(lang: string) { 9 | const i18n = getI18nInstance(lang) 10 | setI18n(i18n) 11 | return i18n 12 | } 13 | -------------------------------------------------------------------------------- /examples/nextjs-swc/src/pages/[lang]/pages-router-demo/index.tsx: -------------------------------------------------------------------------------- 1 | import { GetStaticProps } from 'next' 2 | import { loadCatalog } from '../../../pagesRouterI18n' 3 | import { HomePage } from '../../../components/HomePage' 4 | 5 | import linguiConfig from '../../../../lingui.config' 6 | import type { GetStaticPaths } from 'next' 7 | 8 | export const getStaticPaths = (async () => { 9 | const paths = linguiConfig.locales.map((lang) => ({ params: { lang } })) 10 | 11 | return { 12 | paths, 13 | fallback: false 14 | } 15 | }) satisfies GetStaticPaths 16 | 17 | export const getStaticProps: GetStaticProps = async (ctx) => { 18 | const locale = ctx.params?.lang 19 | const translation = await loadCatalog( 20 | typeof locale === 'string' ? locale : 'en' 21 | ) 22 | 23 | return { 24 | props: { 25 | translation 26 | } 27 | } 28 | } 29 | 30 | export default HomePage 31 | -------------------------------------------------------------------------------- /examples/nextjs-swc/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { i18n } from '@lingui/core' 2 | import { I18nProvider } from '@lingui/react' 3 | import '../styles/globals.css' 4 | import type { AppProps } from 'next/app' 5 | import { useLinguiInit } from '../pagesRouterI18n' 6 | 7 | function MyApp({ Component, pageProps }: AppProps) { 8 | useLinguiInit(pageProps.translation) 9 | 10 | return ( 11 | 12 | 13 | 14 | ) 15 | } 16 | 17 | export default MyApp 18 | -------------------------------------------------------------------------------- /examples/nextjs-swc/src/styles/Index.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | min-height: 100vh; 3 | padding: 0 0.5rem; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items: center; 8 | } 9 | 10 | .main { 11 | padding: 5rem 0; 12 | flex: 1; 13 | display: flex; 14 | flex-direction: column; 15 | justify-content: center; 16 | align-items: center; 17 | } 18 | 19 | .title a { 20 | color: #0070f3; 21 | text-decoration: none; 22 | } 23 | 24 | .title a:hover, 25 | .title a:focus, 26 | .title a:active { 27 | text-decoration: underline; 28 | } 29 | 30 | .title { 31 | margin-bottom: 0; 32 | margin-top: 2rem; 33 | line-height: 1.15; 34 | font-size: 4rem; 35 | } 36 | 37 | .title, 38 | .description { 39 | text-align: center; 40 | } 41 | 42 | .description { 43 | /* line-height: 1.5; */ 44 | /* font-size: 1.5rem; */ 45 | max-width: 600px; 46 | text-align: left; 47 | } 48 | -------------------------------------------------------------------------------- /examples/nextjs-swc/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 7 | } 8 | 9 | a { 10 | color: inherit; 11 | text-decoration: none; 12 | } 13 | 14 | * { 15 | box-sizing: border-box; 16 | } 17 | -------------------------------------------------------------------------------- /examples/nextjs-swc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": true, 12 | "noUncheckedIndexedAccess": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "noEmit": true, 15 | "esModuleInterop": true, 16 | "module": "esnext", 17 | "moduleResolution": "Bundler", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | // "downlevelIteration": true, 21 | "jsx": "preserve", 22 | "incremental": true, 23 | "plugins": [ 24 | { 25 | "name": "next" 26 | } 27 | ] 28 | }, 29 | "include": [ 30 | "next-env.d.ts", 31 | "src/**/*.ts", 32 | "src/**/*.tsx", 33 | ".next/types/**/*.ts" 34 | ], 35 | "exclude": [ 36 | "node_modules" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /examples/react-native/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ["@react-native-community"], 4 | }; 5 | -------------------------------------------------------------------------------- /examples/react-native/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | 16 | # Temporary files created by Metro to check the health of the file watcher 17 | .metro-health-check* 18 | 19 | # js translation files should be generated as part of build process 20 | #src/locales/**/*.js 21 | 22 | .yarn/* 23 | !.yarn/patches 24 | !.yarn/plugins 25 | !.yarn/releases 26 | !.yarn/sdks 27 | !.yarn/versions 28 | -------------------------------------------------------------------------------- /examples/react-native/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "trailingComma": "all", 4 | "tabWidth": 2, 5 | "bracketSpacing": true, 6 | "printWidth": 90 7 | } 8 | -------------------------------------------------------------------------------- /examples/react-native/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /examples/react-native/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "js-lingui-demo", 4 | "description": "This a simple demo app for lingui.js", 5 | "slug": "js-lingui-demo", 6 | "version": "2.0.1", 7 | "orientation": "portrait", 8 | "icon": "./assets/icon.png", 9 | "userInterfaceStyle": "light", 10 | "newArchEnabled": true, 11 | "splash": { 12 | "image": "./assets/splash.png", 13 | "resizeMode": "contain", 14 | "backgroundColor": "#ffffff" 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "ios": { 20 | "supportsTablet": true 21 | }, 22 | "android": { 23 | "adaptiveIcon": { 24 | "foregroundImage": "./assets/adaptive-icon.png", 25 | "backgroundColor": "#ffffff" 26 | } 27 | }, 28 | "web": { 29 | "favicon": "./assets/favicon.png", 30 | "bundler": "metro" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/react-native/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/react-native/assets/adaptive-icon.png -------------------------------------------------------------------------------- /examples/react-native/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/react-native/assets/favicon.png -------------------------------------------------------------------------------- /examples/react-native/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/react-native/assets/icon.png -------------------------------------------------------------------------------- /examples/react-native/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/react-native/assets/splash.png -------------------------------------------------------------------------------- /examples/react-native/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(false); 3 | return { 4 | plugins: ["@lingui/babel-plugin-lingui-macro"], 5 | presets: ["babel-preset-expo"], 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /examples/react-native/lingui.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@lingui/conf').LinguiConfig} */ 2 | module.exports = { 3 | locales: ["en", "cs"], 4 | sourceLocale: "en", 5 | catalogs: [ 6 | { 7 | path: "src/locales/{locale}/messages", 8 | include: ["src"], 9 | }, 10 | ], 11 | format: "po", 12 | }; 13 | -------------------------------------------------------------------------------- /examples/react-native/metro.config.js: -------------------------------------------------------------------------------- 1 | // Learn more https://docs.expo.io/guides/customizing-metro 2 | const { getDefaultConfig } = require("expo/metro-config"); 3 | 4 | const config = getDefaultConfig(__dirname); 5 | const { transformer, resolver } = config; 6 | 7 | config.transformer = { 8 | ...transformer, 9 | babelTransformerPath: require.resolve("@lingui/metro-transformer/expo"), 10 | }; 11 | config.resolver = { 12 | ...resolver, 13 | sourceExts: [...resolver.sourceExts, "po", "pot"], 14 | }; 15 | 16 | module.exports = config; 17 | -------------------------------------------------------------------------------- /examples/react-native/src/Components.tsx: -------------------------------------------------------------------------------- 1 | import { TextProps, Text } from "react-native"; 2 | 3 | export const Heading = (props: Omit) => { 4 | return ( 5 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /examples/react-native/src/PaddedButton.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Button as RNButton, 3 | StyleSheet, 4 | View, 5 | Platform, 6 | ButtonProps, 7 | } from "react-native"; 8 | import React from "react"; 9 | 10 | export const Button = (props: ButtonProps) => ( 11 | 12 | 13 | 14 | ); 15 | 16 | const styles = StyleSheet.create({ 17 | margin: { 18 | ...Platform.select({ 19 | android: { 20 | margin: 10, 21 | }, 22 | }), 23 | }, 24 | }); 25 | -------------------------------------------------------------------------------- /examples/react-native/src/po-types.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.po" { 2 | import type { Messages } from "@lingui/core"; 3 | export const messages: Messages; 4 | } 5 | -------------------------------------------------------------------------------- /examples/react-native/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/remix-vite-babel/.gitignore: -------------------------------------------------------------------------------- 1 | .yarn 2 | node_modules 3 | 4 | /.cache 5 | /build 6 | .env 7 | -------------------------------------------------------------------------------- /examples/remix-vite-babel/app/modules/lingui/config.ts: -------------------------------------------------------------------------------- 1 | import type { LinguiConfig } from "@lingui/conf"; 2 | 3 | const config: LinguiConfig = { 4 | fallbackLocales: { 5 | default: "en", 6 | }, 7 | locales: ["en", "fr"], 8 | catalogs: [ 9 | { 10 | path: "/app/locales/{locale}", 11 | include: ["app"], 12 | }, 13 | ], 14 | }; 15 | 16 | export default config; 17 | -------------------------------------------------------------------------------- /examples/remix-vite-babel/app/modules/lingui/lingui.server.ts: -------------------------------------------------------------------------------- 1 | import config from "./config"; 2 | import { RemixLingui } from "./remix.server"; 3 | import { createCookie } from "@remix-run/node"; 4 | 5 | export const localeCookie = createCookie("lng", { 6 | path: "/", 7 | sameSite: "lax", 8 | secure: process.env.NODE_ENV === "production", 9 | httpOnly: true, 10 | }); 11 | 12 | export const linguiServer = new RemixLingui({ 13 | detection: { 14 | supportedLanguages: config.locales, 15 | fallbackLanguage: 16 | (!!config.fallbackLocales && config.fallbackLocales?.default) || "en", 17 | cookie: localeCookie, 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /examples/remix-vite-babel/lingui.config.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/export 2 | export * from "./app/modules/lingui/config"; 3 | -------------------------------------------------------------------------------- /examples/remix-vite-babel/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { lingui } from "@lingui/vite-plugin"; 2 | import { vitePlugin as remix } from "@remix-run/dev"; 3 | import { installGlobals } from "@remix-run/node"; 4 | import { defineConfig } from "vite"; 5 | import macrosPlugin from "vite-plugin-babel-macros"; 6 | import tsconfigPaths from "vite-tsconfig-paths"; 7 | 8 | installGlobals(); 9 | 10 | export default defineConfig({ 11 | plugins: [ 12 | remix(), 13 | macrosPlugin(), 14 | lingui(), 15 | tsconfigPaths() 16 | ], 17 | }); 18 | -------------------------------------------------------------------------------- /examples/rspack/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/rspack/demo.gif -------------------------------------------------------------------------------- /examples/rspack/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Rspack + React + TS 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/rspack/lingui.config.ts: -------------------------------------------------------------------------------- 1 | import { LinguiConfig } from '@lingui/conf' 2 | 3 | const config: Partial = { 4 | locales: ["en", "fr"], 5 | sourceLocale: "en", 6 | catalogs: [{ 7 | path: "src/locales/{locale}/messages", 8 | include: ["src"] 9 | }], 10 | format: "po" 11 | }; 12 | 13 | export default config; -------------------------------------------------------------------------------- /examples/rspack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rspack-react-ts-starter", 3 | "private": true, 4 | "version": "1.0.0", 5 | "scripts": { 6 | "dev": "rspack serve", 7 | "build": "rspack build", 8 | "extract": "lingui extract", 9 | "compile": "lingui compile --typescript" 10 | }, 11 | "dependencies": { 12 | "@lingui/react": "^4.7.2", 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0" 15 | }, 16 | "devDependencies": { 17 | "@lingui/cli": "^4.7.2", 18 | "@lingui/macro": "^4.7.2", 19 | "@lingui/swc-plugin": "^4.0.7", 20 | "@rspack/cli": "^0.6.2", 21 | "@rspack/core": "^0.6.2", 22 | "@types/react": "^18.2.79", 23 | "@types/react-dom": "18.2.1", 24 | "typescript": "^5.0.4" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/rspack/src/LocaleSwitcher.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useLingui } from '@lingui/react'; 3 | import Locale from './locales'; 4 | 5 | function LocaleSwitcher() { 6 | const { i18n } = useLingui(); 7 | 8 | const handleLocaleChange = (newLocale: Locale) => { 9 | i18n.activate(newLocale); 10 | }; 11 | 12 | return ( 13 |
14 | 15 | 16 | {/* Add more buttons for other supported locales */} 17 |
18 | ); 19 | } 20 | 21 | export default LocaleSwitcher; 22 | -------------------------------------------------------------------------------- /examples/rspack/src/locales.ts: -------------------------------------------------------------------------------- 1 | enum Locale { 2 | ENGLISH = 'en', 3 | FRENCH = 'fr', 4 | } 5 | 6 | export default Locale; 7 | -------------------------------------------------------------------------------- /examples/rspack/src/locales/en/messages.d.ts: -------------------------------------------------------------------------------- 1 | import { Messages } from '@lingui/core'; 2 | declare const messages: Messages; 3 | export { messages }; 4 | -------------------------------------------------------------------------------- /examples/rspack/src/locales/en/messages.ts: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/export const messages=JSON.parse("{\"iHvPFN\":[[\"messagesCount\",\"plural\",{\"one\":[\"There's \",\"#\",\" message in your inbox.\"],\"other\":[\"There are \",\"#\",\" messages in your inbox.\"]}]],\"ItXLVU\":[\"Last login on \",[\"0\"],\".\"],\"8bWV5m\":\"Message Inbox\",\"f8BUjV\":\"See all <0>unread messages or <1>mark them as read.\"}"); -------------------------------------------------------------------------------- /examples/rspack/src/locales/fr/messages.d.ts: -------------------------------------------------------------------------------- 1 | import { Messages } from '@lingui/core'; 2 | declare const messages: Messages; 3 | export { messages }; 4 | -------------------------------------------------------------------------------- /examples/rspack/src/locales/fr/messages.ts: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/export const messages=JSON.parse("{\"iHvPFN\":[[\"messagesCount\",\"plural\",{\"one\":[\"Il y a \",\"#\",\" message dans boîte de réception.\"],\"other\":[\"Il y a \",\"#\",\" messages dans votre boîte de réception.\"]}]],\"ItXLVU\":[\"Last login on \",[\"0\"],\".\"],\"8bWV5m\":\"Boîte de réception de messages.\",\"f8BUjV\":\"Voir tous <0>les messages non lus ou <1>les marquer comme lus.\"}"); -------------------------------------------------------------------------------- /examples/rspack/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | 4 | import { i18n } from "@lingui/core"; 5 | import { I18nProvider } from "@lingui/react"; 6 | import { messages as enMessages } from "./locales/en/messages"; 7 | import { messages as frMessages } from "./locales/fr/messages"; 8 | 9 | import Inbox from "./Inbox"; 10 | 11 | i18n.load({ 12 | "en": enMessages, 13 | "fr": frMessages, 14 | }); 15 | 16 | i18n.activate("en"); 17 | 18 | const App = () => ( 19 | 20 | 21 | 22 | ); 23 | 24 | const container = document.getElementById('root'); 25 | const root = createRoot(container!); 26 | root.render( 27 | 28 | 29 | 30 | ) 31 | -------------------------------------------------------------------------------- /examples/rspack/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "lib": [ 5 | "DOM", 6 | "DOM.Iterable", 7 | "ESNext" 8 | ], 9 | "module": "ESNext", 10 | "skipLibCheck": true, 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true, 21 | }, 22 | "include": [ 23 | "src" 24 | ] 25 | } -------------------------------------------------------------------------------- /examples/tanstack-start/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .yarn 3 | 4 | .DS_Store 5 | .cache 6 | .env 7 | .vercel 8 | .output 9 | .vinxi 10 | 11 | /build/ 12 | /api/ 13 | /server/build 14 | /public/build 15 | .vinxi 16 | # Sentry Config File 17 | .env.sentry-build-plugin 18 | /test-results/ 19 | /playwright-report/ 20 | /blob-report/ 21 | /playwright/.cache/ 22 | -------------------------------------------------------------------------------- /examples/tanstack-start/.prettierignore: -------------------------------------------------------------------------------- 1 | **/build 2 | **/public 3 | pnpm-lock.yaml 4 | routeTree.gen.ts -------------------------------------------------------------------------------- /examples/tanstack-start/README.md: -------------------------------------------------------------------------------- 1 | # Example project using Tanstack Start + Vite + Babel with LinguiJS Plugin 2 | 3 | This is a [Tanstack Start](https://tanstack.com/start/latest) project that demonstrates i18n support with Lingui. 4 | 5 | ## Development 6 | 7 | From your terminal: 8 | 9 | ```sh 10 | yarn install 11 | yarn dev 12 | ``` 13 | 14 | This starts your app in development mode, rebuilding assets on file changes. 15 | -------------------------------------------------------------------------------- /examples/tanstack-start/app.config.ts: -------------------------------------------------------------------------------- 1 | import { lingui } from "@lingui/vite-plugin" 2 | import { defineConfig } from "@tanstack/react-start/config" 3 | import tsConfigPaths from "vite-tsconfig-paths" 4 | 5 | export default defineConfig({ 6 | tsr: { 7 | appDirectory: "src", 8 | }, 9 | react: { 10 | babel: { 11 | plugins: ["@lingui/babel-plugin-lingui-macro"], 12 | }, 13 | }, 14 | vite: { 15 | plugins: [ 16 | lingui(), 17 | tsConfigPaths({ 18 | projects: ["./tsconfig.json"], 19 | }), 20 | ], 21 | }, 22 | }) 23 | -------------------------------------------------------------------------------- /examples/tanstack-start/lingui.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "@lingui/cli" 2 | 3 | export default defineConfig({ 4 | catalogs: [ 5 | { 6 | include: ["src"], 7 | path: "/src/locales/{locale}/messages", 8 | }, 9 | ], 10 | locales: ["fr", "en"], 11 | sourceLocale: "en", 12 | }) 13 | -------------------------------------------------------------------------------- /examples/tanstack-start/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /examples/tanstack-start/public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/tanstack-start/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/tanstack-start/public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/tanstack-start/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /examples/tanstack-start/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/tanstack-start/public/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/tanstack-start/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/tanstack-start/public/favicon-16x16.png -------------------------------------------------------------------------------- /examples/tanstack-start/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/tanstack-start/public/favicon-32x32.png -------------------------------------------------------------------------------- /examples/tanstack-start/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/tanstack-start/public/favicon.ico -------------------------------------------------------------------------------- /examples/tanstack-start/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingui/js-lingui/37f40ec18928b357c07a228947b2bf071e92449e/examples/tanstack-start/public/favicon.png -------------------------------------------------------------------------------- /examples/tanstack-start/public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/api.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createStartAPIHandler, 3 | defaultAPIFileRouteHandler, 4 | } from "@tanstack/react-start/api" 5 | import { 6 | defaultLocale, 7 | dynamicActivate, 8 | isLocaleValid, 9 | } from "./modules/lingui/i18n" 10 | 11 | export default createStartAPIHandler(async (ctx) => { 12 | // Define the locale based on the Accept-Language header 13 | const headerLocale = ctx.request.headers.get("Accept-Language") ?? "" 14 | await dynamicActivate( 15 | isLocaleValid(headerLocale) ? headerLocale : defaultLocale 16 | ) 17 | 18 | return defaultAPIFileRouteHandler(ctx) 19 | }) 20 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/client.tsx: -------------------------------------------------------------------------------- 1 | /// 2 | import { i18n } from "@lingui/core" 3 | import { hydrateRoot } from "react-dom/client" 4 | import { StartClient } from "@tanstack/react-start" 5 | import { dynamicActivate } from "./modules/lingui/i18n" 6 | 7 | import { createRouter } from "./router" 8 | 9 | // The lang should be set by the server 10 | dynamicActivate(document.documentElement.lang) 11 | 12 | const router = createRouter({ i18n }) 13 | 14 | hydrateRoot(document, ) 15 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/components/PostError.tsx: -------------------------------------------------------------------------------- 1 | import { ErrorComponent, ErrorComponentProps } from "@tanstack/react-router" 2 | 3 | export function PostErrorComponent({ error }: ErrorComponentProps) { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/components/UserError.tsx: -------------------------------------------------------------------------------- 1 | import { ErrorComponent, ErrorComponentProps } from "@tanstack/react-router" 2 | 3 | export function UserErrorComponent({ error }: ErrorComponentProps) { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/functions/deferred.ts: -------------------------------------------------------------------------------- 1 | import { createServerFn } from "@tanstack/react-start" 2 | 3 | export const personServerFn = createServerFn({ method: "GET" }) 4 | .validator((d: string) => d) 5 | .handler(({ data: name }) => { 6 | return { name, randomNumber: Math.floor(Math.random() * 100) } 7 | }) 8 | 9 | export const slowServerFn = createServerFn({ method: "GET" }) 10 | .validator((d: string) => d) 11 | .handler(async ({ data: name }) => { 12 | await new Promise((r) => setTimeout(r, 1000)) 13 | return { name, randomNumber: Math.floor(Math.random() * 100) } 14 | }) 15 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/global-middleware.ts: -------------------------------------------------------------------------------- 1 | import { registerGlobalMiddleware } from "@tanstack/react-start" 2 | import { logMiddleware } from "./utils/loggingMiddleware" 3 | 4 | registerGlobalMiddleware({ 5 | middleware: [logMiddleware], 6 | }) 7 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/modules/lingui/i18n.ts: -------------------------------------------------------------------------------- 1 | import { i18n } from "@lingui/core" 2 | 3 | export const locales = { 4 | en: "English", 5 | fr: "French", 6 | } 7 | 8 | export const isLocaleValid = (locale: string) => 9 | Object.keys(locales).includes(locale) 10 | 11 | export const defaultLocale = "en" 12 | 13 | /** 14 | * We do a dynamic import of just the catalog that we need 15 | * @param locale any locale string 16 | */ 17 | export async function dynamicActivate(locale: string) { 18 | const { messages } = await import(`../../locales/${locale}/messages.po`) 19 | i18n.load(locale, messages) 20 | i18n.activate(locale) 21 | } 22 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/routes/_pathlessLayout.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from "@lingui/react/macro" 2 | import { Outlet, createFileRoute } from "@tanstack/react-router" 3 | 4 | export const Route = createFileRoute("/_pathlessLayout")({ 5 | component: LayoutComponent, 6 | }) 7 | 8 | function LayoutComponent() { 9 | return ( 10 |
11 |
12 | I'm a layout 13 |
14 |
15 | 16 |
17 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/routes/_pathlessLayout/_nested-layout/route-a.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from "@lingui/react/macro" 2 | import { createFileRoute } from "@tanstack/react-router" 3 | 4 | export const Route = createFileRoute("/_pathlessLayout/_nested-layout/route-a")( 5 | { 6 | component: LayoutAComponent, 7 | } 8 | ) 9 | 10 | function LayoutAComponent() { 11 | return ( 12 |
13 | I'm A! 14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/routes/_pathlessLayout/_nested-layout/route-b.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from "@lingui/react/macro" 2 | import { createFileRoute } from "@tanstack/react-router" 3 | 4 | export const Route = createFileRoute("/_pathlessLayout/_nested-layout/route-b")( 5 | { 6 | component: LayoutBComponent, 7 | } 8 | ) 9 | 10 | function LayoutBComponent() { 11 | return ( 12 |
13 | I'm B! 14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/routes/api/users.$id.ts: -------------------------------------------------------------------------------- 1 | import { json } from "@tanstack/react-start" 2 | import { createAPIFileRoute } from "@tanstack/react-start/api" 3 | import axios from "redaxios" 4 | import type { User } from "../../utils/users" 5 | import { i18n } from "@lingui/core" 6 | 7 | export const APIRoute = createAPIFileRoute("/api/users/$id")({ 8 | GET: async ({ request, params }) => { 9 | console.info(`Fetching users by id=${params.id}... @`, request.url) 10 | try { 11 | const res = await axios.get( 12 | "https://jsonplaceholder.typicode.com/users/" + params.id 13 | ) 14 | 15 | return json({ 16 | id: res.data.id, 17 | name: res.data.name, 18 | email: res.data.email, 19 | }) 20 | } catch (e) { 21 | console.error(e) 22 | return json({ error: i18n._("User not found") }, { status: 404 }) 23 | } 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/routes/api/users.ts: -------------------------------------------------------------------------------- 1 | import { json } from "@tanstack/react-start" 2 | import { createAPIFileRoute } from "@tanstack/react-start/api" 3 | import axios from "redaxios" 4 | import type { User } from "../../utils/users" 5 | 6 | export const APIRoute = createAPIFileRoute("/api/users")({ 7 | GET: async ({ request }) => { 8 | console.info("Fetching users... @", request.url) 9 | const res = await axios.get>( 10 | "https://jsonplaceholder.typicode.com/users" 11 | ) 12 | 13 | const list = res.data.slice(0, 10) 14 | 15 | return json(list.map((u) => ({ id: u.id, name: u.name, email: u.email }))) 16 | }, 17 | }) 18 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/routes/index.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from "@lingui/react/macro" 2 | import { createFileRoute } from "@tanstack/react-router" 3 | 4 | export const Route = createFileRoute("/")({ 5 | component: Home, 6 | }) 7 | 8 | function Home() { 9 | return ( 10 |
11 |

12 | Welcome Home!!! 13 |

14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/routes/posts.index.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from "@lingui/react/macro" 2 | import { createFileRoute } from "@tanstack/react-router" 3 | 4 | export const Route = createFileRoute("/posts/")({ 5 | component: PostsIndexComponent, 6 | }) 7 | 8 | function PostsIndexComponent() { 9 | return ( 10 |
11 | Select a post. 12 |
13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/routes/redirect.tsx: -------------------------------------------------------------------------------- 1 | import { createFileRoute, redirect } from "@tanstack/react-router" 2 | 3 | export const Route = createFileRoute("/redirect")({ 4 | beforeLoad: async () => { 5 | throw redirect({ 6 | to: "/posts", 7 | }) 8 | }, 9 | }) 10 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/routes/users.index.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from "@lingui/react/macro" 2 | import { createFileRoute } from "@tanstack/react-router" 3 | 4 | export const Route = createFileRoute("/users/")({ 5 | component: UsersIndexComponent, 6 | }) 7 | 8 | function UsersIndexComponent() { 9 | return ( 10 |
11 | Select a user. 12 |
13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/ssr.tsx: -------------------------------------------------------------------------------- 1 | /// 2 | import { i18n } from "@lingui/core" 3 | import { 4 | createStartHandler, 5 | defaultStreamHandler, 6 | defineEventHandler, 7 | } from "@tanstack/react-start/server" 8 | import { getRouterManifest } from "@tanstack/react-start/router-manifest" 9 | 10 | import { createRouter } from "./router" 11 | import { setupLocaleFromRequest } from "./modules/lingui/i18n.server" 12 | 13 | export default defineEventHandler(async (event) => { 14 | await setupLocaleFromRequest() 15 | 16 | return createStartHandler({ 17 | createRouter: () => { 18 | return createRouter({ i18n }) 19 | }, 20 | getRouterManifest, 21 | })(defaultStreamHandler)(event) 22 | }) 23 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/styles/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | html { 7 | color-scheme: light dark; 8 | } 9 | 10 | * { 11 | @apply border-gray-200 dark:border-gray-800; 12 | } 13 | 14 | html, 15 | body { 16 | @apply text-gray-900 bg-gray-50 dark:bg-gray-950 dark:text-gray-200; 17 | } 18 | 19 | .using-mouse * { 20 | outline: none !important; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/tanstack-start/src/utils/users.tsx: -------------------------------------------------------------------------------- 1 | export type User = { 2 | id: number 3 | name: string 4 | email: string 5 | } 6 | 7 | export const DEPLOY_URL = "http://localhost:3000" 8 | -------------------------------------------------------------------------------- /examples/tanstack-start/tailwind.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ['./src/**/*.{js,jsx,ts,tsx}'], 4 | } 5 | -------------------------------------------------------------------------------- /examples/tanstack-start/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts", "**/*.tsx"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "jsx": "react-jsx", 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 10 | "isolatedModules": true, 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true, 13 | "target": "ES2022", 14 | "allowJs": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "~/*": ["./src/*"] 19 | }, 20 | "noEmit": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | 27 | .pnp.* 28 | .yarn/* 29 | !.yarn/patches 30 | !.yarn/plugins 31 | !.yarn/releases 32 | !.yarn/sdks 33 | !.yarn/versions 34 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/lingui.config.ts: -------------------------------------------------------------------------------- 1 | import type { LinguiConfig } from "@lingui/conf" 2 | 3 | const config: LinguiConfig = { 4 | locales: ["en", "pl"], 5 | catalogs: [ 6 | { 7 | path: "src/locales/{locale}", 8 | include: ["src"], 9 | }, 10 | ], 11 | } 12 | 13 | export default config 14 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-project", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "messages:extract": "lingui extract", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@lingui/core": "^5.0.0-next.3", 14 | "@lingui/react": "^5.0.0-next.3", 15 | "react": "^18.2.0", 16 | "react-dom": "^18.2.0" 17 | }, 18 | "devDependencies": { 19 | "@lingui/babel-plugin-lingui-macro": "5.0.0-next.3", 20 | "@lingui/cli": "^5.0.0-next.3", 21 | "@lingui/vite-plugin": "^5.0.0-next.3", 22 | "@types/react": "^18.0.28", 23 | "@types/react-dom": "^18.0.11", 24 | "@vitejs/plugin-react": "^4.3.2", 25 | "typescript": "^4.9.3", 26 | "vite": "^5.4.9" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | transition: filter 300ms; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.react:hover { 18 | filter: drop-shadow(0 0 2em #61dafbaa); 19 | } 20 | 21 | @keyframes logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | 30 | @media (prefers-reduced-motion: no-preference) { 31 | a:nth-of-type(2) .logo { 32 | animation: logo-spin infinite 20s linear; 33 | } 34 | } 35 | 36 | .card { 37 | padding: 2em; 38 | } 39 | 40 | .read-the-docs { 41 | color: #888; 42 | } 43 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/src/i18n.ts: -------------------------------------------------------------------------------- 1 | import { i18n } from "@lingui/core" 2 | 3 | /** 4 | * Load messages for requested locale and activate it. 5 | * This function isn't part of the LinguiJS library because there are 6 | * many ways how to load messages — from REST API, from file, from cache, etc. 7 | */ 8 | export async function loadCatalog(locale: string) { 9 | const catalog = await import(`./locales/${locale}.po`) 10 | i18n.loadAndActivate({ locale, messages: catalog.messages }) 11 | } 12 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/vite-project-react-babel/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite" 2 | import react from "@vitejs/plugin-react" 3 | import { lingui } from "@lingui/vite-plugin" 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [ 8 | react({ 9 | babel: { 10 | plugins: ["@lingui/babel-plugin-lingui-macro"], 11 | }, 12 | }), 13 | lingui(), 14 | ], 15 | }) 16 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | 27 | .pnp.* 28 | .yarn/* 29 | !.yarn/patches 30 | !.yarn/plugins 31 | !.yarn/releases 32 | !.yarn/sdks 33 | !.yarn/versions 34 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/lingui.config.ts: -------------------------------------------------------------------------------- 1 | import type { LinguiConfig } from "@lingui/conf" 2 | 3 | const config: LinguiConfig = { 4 | locales: ["en", "pl"], 5 | catalogs: [ 6 | { 7 | path: "src/locales/{locale}", 8 | include: ["src"], 9 | }, 10 | ], 11 | } 12 | 13 | export default config 14 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-project-react-swc", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "lingui:extract": "lingui extract", 10 | "preview": "vite preview" 11 | }, 12 | "resolutions": { 13 | "@swc/core": "1.5.7" 14 | }, 15 | "dependencies": { 16 | "@lingui/core": "^5.0.0-next.3", 17 | "@lingui/react": "^5.0.0-next.3", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0" 20 | }, 21 | "devDependencies": { 22 | "@lingui/cli": "^5.0.0-next.3", 23 | "@lingui/swc-plugin": "5.0.0-next.2", 24 | "@lingui/vite-plugin": "^5.0.0-next.3", 25 | "@types/react": "^18.0.28", 26 | "@types/react-dom": "^18.0.11", 27 | "@vitejs/plugin-react-swc": "3.7.0", 28 | "typescript": "^4.9.3", 29 | "vite": "5.4.9" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | transition: filter 300ms; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.react:hover { 18 | filter: drop-shadow(0 0 2em #61dafbaa); 19 | } 20 | 21 | @keyframes logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | 30 | @media (prefers-reduced-motion: no-preference) { 31 | a:nth-of-type(2) .logo { 32 | animation: logo-spin infinite 20s linear; 33 | } 34 | } 35 | 36 | .card { 37 | padding: 2em; 38 | } 39 | 40 | .read-the-docs { 41 | color: #888; 42 | } 43 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/src/i18n.ts: -------------------------------------------------------------------------------- 1 | import { i18n } from "@lingui/core" 2 | 3 | /** 4 | * Load messages for requested locale and activate it. 5 | * This function isn't part of the LinguiJS library because there are 6 | * many ways how to load messages — from REST API, from file, from cache, etc. 7 | */ 8 | export async function loadCatalog(locale: string) { 9 | const { messages } = await import(`./locales/${locale}.po`) 10 | i18n.loadAndActivate({ locale, messages }) 11 | } 12 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import ReactDOM from "react-dom/client" 3 | import App from "./App" 4 | import "./index.css" 5 | import { loadCatalog } from "./i18n" 6 | 7 | // load initial language, you can detect here a user language with your preferred method 8 | await loadCatalog("en") 9 | 10 | ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( 11 | 12 | 13 | 14 | ) 15 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/vite-project-react-swc/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite" 2 | import react from "@vitejs/plugin-react-swc" 3 | import { lingui } from "@lingui/vite-plugin" 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [ 8 | react({ 9 | plugins: [["@lingui/swc-plugin", {}]], 10 | }), 11 | lingui(), 12 | ], 13 | }) 14 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "5.3.2", 3 | "packages": ["packages/*"], 4 | "npmClient": "yarn", 5 | "command": { 6 | "version": { 7 | "message": "chore(release): published %s [skip ci]", 8 | "ignoreChanges": [ 9 | "**/CHANGELOG.md", 10 | "**/examples/*", 11 | "**/node_modules/**", 12 | "**/package.json", 13 | "**/website/**", 14 | "**/*.md", 15 | "test/**" 16 | ] 17 | }, 18 | "publish": { 19 | "allowBranch": ["main", "next"], 20 | "ignoreChanges": [ 21 | "**/CHANGELOG.md", 22 | "**/examples/*", 23 | "**/node_modules/**", 24 | "**/package.json", 25 | "**/website/**", 26 | "**/*.md", 27 | "test/**" 28 | ] 29 | } 30 | }, 31 | "$schema": "node_modules/lerna/schemas/lerna-schema.json" 32 | } 33 | -------------------------------------------------------------------------------- /packages/babel-plugin-extract-messages/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from "unbuild" 2 | 3 | export default defineBuildConfig({ 4 | externals: ["@babel/core", "@babel/types", "@babel/traverse"], 5 | }) 6 | -------------------------------------------------------------------------------- /packages/babel-plugin-extract-messages/test/fixtures/js-call-expression.js: -------------------------------------------------------------------------------- 1 | const msg = i18n._("Message") 2 | 3 | const withDescription = i18n._("Description", {}, { comment: "description" }) 4 | 5 | const withId = i18n._("ID", {}, { message: "Message with id" }) 6 | 7 | const withValues = i18n._("Values {param}", { param: param }) 8 | 9 | const withContext = i18n._("Some id", {}, { context: "Context1" }) 10 | 11 | // from message descriptor 12 | i18n._({ 13 | id: "my.id", 14 | message: "My Id Message", 15 | comment: "My comment", 16 | }) 17 | 18 | // support alias 19 | i18n.t("Aliased Message") 20 | 21 | // from message descriptor 22 | i18n.t({ 23 | id: "my.id", 24 | message: "My Id Message", 25 | comment: "My comment", 26 | }) 27 | -------------------------------------------------------------------------------- /packages/babel-plugin-extract-messages/test/fixtures/js-message-descriptor.js: -------------------------------------------------------------------------------- 1 | const msg = /*i18n*/ { id: "Message" } 2 | 3 | const withDescription = /*i18n*/ { id: "Description", comment: "description" } 4 | 5 | const withId = /*i18n*/ { id: "ID", message: "Message with id" } 6 | 7 | const withValues = /*i18n*/ { 8 | id: "Values {param} {0} {name} {value}", 9 | values: { 10 | param: param, 11 | 0: user.getName(), 12 | ["name"]: "foo", 13 | // prettier-ignore 14 | value: user 15 | ? user.name 16 | : null, 17 | }, 18 | } 19 | /** 20 | * With values passed as variable 21 | */ 22 | const values = {} 23 | const withValues2 = /*i18n*/ { id: "Values {param} {0}", values } 24 | 25 | const withContext = /*i18n*/ { id: "Some id", context: "Context1" } 26 | -------------------------------------------------------------------------------- /packages/babel-plugin-extract-messages/test/fixtures/jsx-with-macros.js: -------------------------------------------------------------------------------- 1 | import { Trans } from "@lingui/react/macro" 2 | import { t, plural } from "@lingui/core/macro" 3 | ;Hi, my name is {name} 4 | ;Some message 5 | ;Some other message 6 | ;Some message 7 | ; 8 | ; 14 | -------------------------------------------------------------------------------- /packages/babel-plugin-extract-messages/test/fixtures/jsx-without-macros.js: -------------------------------------------------------------------------------- 1 | import { Trans } from "@lingui/react" 2 | 3 | ; 4 | 5 | ; 6 | ; 7 | ; 8 | ; 9 | ; 10 | ; 11 | ; 12 | 13 | -------------------------------------------------------------------------------- /packages/babel-plugin-extract-messages/test/fixtures/jsx-without-trans.js: -------------------------------------------------------------------------------- 1 | import { Plural } from "@lingui/react/macro" 2 | ; 3 | ; 4 | -------------------------------------------------------------------------------- /packages/babel-plugin-extract-messages/test/fixtures/lingui.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | locales: ["en", "cs"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/babel-plugin-extract-messages/test/fixtures/without-lingui.js: -------------------------------------------------------------------------------- 1 | import { Select } from "awesome-form-lib" 2 | import { Trans } from "awesome-animation-lib" 3 | 4 | ; 5 | Displaced element 6 | 7 | ;