} {...props} />;
16 | };
17 |
--------------------------------------------------------------------------------
/packages/react/src/hooks.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from 'react';
2 |
3 | export const useRerender = () => {
4 | const [instance, setCounter] = useState(0);
5 |
6 | const rerender = useCallback(() => {
7 | setCounter((num) => num + 1);
8 | }, [setCounter]);
9 | return { instance, rerender };
10 | };
11 |
--------------------------------------------------------------------------------
/packages/react/src/index.ts:
--------------------------------------------------------------------------------
1 | export { useTranslate, UseTranslateResult } from './useTranslate';
2 | export {
3 | TolgeeProvider,
4 | TolgeeProviderProps,
5 | getProviderInstance,
6 | } from './TolgeeProvider';
7 | export { T } from './T';
8 | export { useTolgee } from './useTolgee';
9 | export { GlobalContextPlugin } from './GlobalContextPlugin';
10 | export { useTolgeeSSR } from './useTolgeeSSR';
11 | export { TBase } from './TBase';
12 | export * from './types';
13 |
14 | export * from '@tolgee/web';
15 |
--------------------------------------------------------------------------------
/packages/react/src/server.ts:
--------------------------------------------------------------------------------
1 | export { TBase } from './TBase';
2 | export * from './types';
3 | export * from './createServerInstance';
4 |
5 | export * from '@tolgee/web';
6 |
--------------------------------------------------------------------------------
/packages/react/src/useTolgee.ts:
--------------------------------------------------------------------------------
1 | import { TolgeeEvent, TolgeeInstance } from '@tolgee/web';
2 | import { useEffect } from 'react';
3 | import { useRerender } from './hooks';
4 | import { useTolgeeContext } from './useTolgeeContext';
5 |
6 | export const useTolgee = (events?: TolgeeEvent[]): TolgeeInstance => {
7 | const { tolgee } = useTolgeeContext();
8 |
9 | const { rerender } = useRerender();
10 |
11 | useEffect(() => {
12 | const listeners = events?.map((e) => tolgee.on(e, rerender));
13 | return () => {
14 | listeners?.forEach((listener) => listener.unsubscribe());
15 | };
16 | }, [events?.join(':')]);
17 |
18 | return tolgee;
19 | };
20 |
--------------------------------------------------------------------------------
/packages/react/src/useTolgeeContext.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import { getGlobalContext } from './GlobalContextPlugin';
3 | import { getProviderInstance } from './TolgeeProvider';
4 |
5 | export const useTolgeeContext = () => {
6 | const TolgeeProviderContext = getProviderInstance();
7 | const context = useContext(TolgeeProviderContext) || getGlobalContext();
8 | if (!context) {
9 | throw new Error(
10 | "Couldn't find tolgee instance, did you forgot to use `TolgeeProvider`?"
11 | );
12 | }
13 | return context;
14 | };
15 |
--------------------------------------------------------------------------------
/packages/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2017",
4 | "module": "esnext",
5 | "declaration": true,
6 | "outDir": "./lib",
7 | "moduleResolution": "node",
8 | "skipLibCheck": true,
9 | "lib": [
10 | "es2018",
11 | "es2020",
12 | "dom"
13 | ],
14 | "experimentalDecorators": true,
15 | "emitDecoratorMetadata": true,
16 | "emitDeclarationOnly": true,
17 | "esModuleInterop": true,
18 | "strict": true,
19 | "jsx": "react",
20 | "downlevelIteration": true,
21 | "paths": {}
22 | },
23 | "include": [
24 | "./src/**/*.ts"
25 | ],
26 | "exclude": [
27 | "node_modules"
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/packages/react/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "include": ["src/index.ts", "src/server.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/react/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "include": ["src/**/*.ts?"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/svelte/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | # Output
4 | .output
5 | .vercel
6 | /.svelte-kit
7 | /build
8 | /dist
9 |
10 | # OS
11 | .DS_Store
12 | Thumbs.db
13 |
14 | # Env
15 | .env
16 | .env.*
17 | !.env.example
18 | !.env.test
19 |
20 | # Vite
21 | vite.config.js.timestamp-*
22 | vite.config.ts.timestamp-*
23 |
--------------------------------------------------------------------------------
/packages/svelte/.prettierignore:
--------------------------------------------------------------------------------
1 | # Package Managers
2 | package-lock.json
3 | pnpm-lock.yaml
4 | yarn.lock
5 |
--------------------------------------------------------------------------------
/packages/svelte/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": false,
3 | "singleQuote": true,
4 | "trailingComma": "none",
5 | "printWidth": 100,
6 | "plugins": ["prettier-plugin-svelte"],
7 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/svelte/src/app.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | // See https://kit.svelte.dev/docs/types#app
4 | // for information about these interfaces
5 | // and what to do when importing types
6 | declare namespace App {
7 | // interface Locals {}
8 | // interface Platform {}
9 | // interface PrivateEnv {}
10 | // interface PublicEnv {}
11 | }
12 |
--------------------------------------------------------------------------------
/packages/svelte/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | %sveltekit.head%
8 |
9 |
10 | %sveltekit.body%
11 |
12 |
13 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/GlobalContextPlugin.ts:
--------------------------------------------------------------------------------
1 | import type { TolgeePlugin } from '@tolgee/web';
2 | import type { TolgeeSvelteContext } from './types';
3 |
4 | let globalContext: TolgeeSvelteContext | undefined;
5 |
6 | export const GlobalContextPlugin = (): TolgeePlugin => (tolgee) => {
7 | globalContext = {
8 | tolgee
9 | };
10 | return tolgee;
11 | };
12 |
13 | export function getGlobalContext() {
14 | return globalContext;
15 | }
16 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/T.svelte:
--------------------------------------------------------------------------------
1 |
18 |
19 | {$t({
20 | key: keyName,
21 | params: params,
22 | noWrap: noWrap,
23 | defaultValue: defaultValue,
24 | ns,
25 | language
26 | })}
27 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/TolgeeProvider.svelte:
--------------------------------------------------------------------------------
1 |
22 |
23 | {#if !isLoading}
24 |
25 | {:else if fallback}
26 | {fallback}
27 | {:else}
28 |
29 | {/if}
30 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/__integration/components/Namespaces.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 | {#if $isLoading}
8 |
Loading...
9 | {/if}
10 |
{$t('test')}
11 |
12 | {$t('test_english_fallback')}
13 |
14 |
15 | {$t('non_existant', 'Non existant')}
16 |
17 |
18 | {$t('fallback', { ns: 'invalid' })}
19 |
20 |
21 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/__integration/components/TestGetTolgee.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
{String($tolgee.getLanguage())}
11 |
{String($tolgee.getPendingLanguage())}
12 |
{String($tolgee.isFetching())}
13 |
{String($tolgee.isLoading())}
14 |
{String($tolgee.isInitialLoading())}
15 |
{String($tolgee.isRunning())}
16 |
17 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/__integration/components/TestProviderComponent.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Loading...
20 |
21 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/__integration/components/TestTranslateComponent.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 | Loading...
12 |
13 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/__integration/components/TestTranslateComponentInside.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | {$t('peter_dogs', { dogsCount: 5 })}
9 |
10 |
11 | {$t('hello_world')}
12 |
13 |
14 | {$t({ key: 'hello_world', noWrap: true })}
15 |
16 |
17 | {$t('non_existant', 'Non existant')}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/__integration/mockCoreFetch.ts:
--------------------------------------------------------------------------------
1 | import 'node-fetch';
2 | import { getMocker } from '@tolgee/testing/mockData.js';
3 | import createFetchMock from 'vitest-fetch-mock';
4 | import { vi } from 'vitest';
5 |
6 | const fetchMocker = createFetchMock(vi);
7 |
8 | export const mockCoreFetch = () => {
9 | const mocker = getMocker();
10 |
11 | const fetch = fetchMocker.mockResponse((req) => {
12 | return mocker.getDataForUrl(req.url);
13 | });
14 |
15 | return { ...mocker.mockData, fetch, resolveAll: mocker.resolveAll };
16 | };
17 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/__testUtil/TolgeeProviderFallback.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 | It's rendered!
10 |
11 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/__testUtil/TolgeeProviderSlotTest.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 | loading
10 | It's rendered!
11 |
12 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/getTolgee.ts:
--------------------------------------------------------------------------------
1 | import { readable } from 'svelte/store';
2 | import type { TolgeeEvent } from '@tolgee/web';
3 | import { getTolgeeContext } from './getTolgeeContext';
4 |
5 | export const getTolgee = (events?: TolgeeEvent[]) => {
6 | const tolgeeContext = getTolgeeContext();
7 |
8 | const tolgee = tolgeeContext.tolgee;
9 |
10 | const { subscribe } = readable(tolgee, (set) => {
11 | const listeners = events?.map((e) =>
12 | tolgee.on(e, () => {
13 | set({ ...tolgee });
14 | })
15 | );
16 |
17 | return () => listeners?.forEach((listener) => listener.unsubscribe());
18 | });
19 |
20 | return { subscribe, value: tolgee };
21 | };
22 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/getTolgeeContext.ts:
--------------------------------------------------------------------------------
1 | import { getContext } from 'svelte';
2 | import { getGlobalContext } from './GlobalContextPlugin';
3 | import type { TolgeeSvelteContext } from './types';
4 |
5 | /**
6 | * Returns Tolgee context.
7 | * @throws Error when context is not defined.
8 | */
9 | export const getTolgeeContext = (): TolgeeSvelteContext => {
10 | const context = (getContext('tolgeeContext') || getGlobalContext()) as TolgeeSvelteContext;
11 | if (context === undefined) {
12 | throw Error(
13 | 'Tolgee context is undefined. Trying to use getTranslate method or T component outside TolgeeProvider?'
14 | );
15 | }
16 | return context;
17 | };
18 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | export { default as T } from './T.svelte';
2 | export { default as getTranslate } from './getTranslate';
3 | export { default as TolgeeProvider } from './TolgeeProvider.svelte';
4 | export { getTolgeeContext } from './getTolgeeContext';
5 | export { GlobalContextPlugin } from './GlobalContextPlugin';
6 | export { getTolgee } from './getTolgee';
7 |
8 | export * from '@tolgee/web';
9 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/types.ts:
--------------------------------------------------------------------------------
1 | import type { TolgeeInstance } from '@tolgee/web';
2 |
3 | export type TolgeeSvelteContext = {
4 | tolgee: TolgeeInstance;
5 | };
6 |
--------------------------------------------------------------------------------
/packages/svelte/src/routes/+page.svelte:
--------------------------------------------------------------------------------
1 | Welcome to your library project
2 | Create your package using @sveltejs/package and preview/showcase your work with SvelteKit
3 | Visit kit.svelte.dev to read the documentation
4 |
--------------------------------------------------------------------------------
/packages/svelte/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tolgee/tolgee-js/ea8ffc97dcfec4a1ea7b06abde18d35e208cfe91/packages/svelte/static/favicon.png
--------------------------------------------------------------------------------
/packages/svelte/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from '@sveltejs/adapter-auto';
2 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors
7 | // for more information about preprocessors
8 | preprocess: vitePreprocess(),
9 |
10 | kit: {
11 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
12 | // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
13 | // See https://kit.svelte.dev/docs/adapters for more information about adapters.
14 | adapter: adapter()
15 | }
16 | };
17 |
18 | export default config;
19 |
--------------------------------------------------------------------------------
/packages/svelte/tests/setup.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/vitest';
2 |
--------------------------------------------------------------------------------
/packages/svelte/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "resolveJsonModule": true,
9 | "skipLibCheck": true,
10 | "sourceMap": true,
11 | "strict": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node"
14 | },
15 | "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte", "jest-setup.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/svelte/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from '@sveltejs/kit/vite';
2 | import { defineConfig } from 'vitest/config';
3 | import { svelteTesting } from '@testing-library/svelte/vite';
4 |
5 | export default defineConfig({
6 | plugins: [sveltekit(), svelteTesting()],
7 | test: {
8 | include: ['src/**/*.{test,spec}.{js,ts}'],
9 | setupFiles: ['./tests/setup.ts'],
10 | globals: true,
11 | environment: 'jsdom'
12 | }
13 | });
14 |
--------------------------------------------------------------------------------
/packages/testing/createResolvablePromise.ts:
--------------------------------------------------------------------------------
1 | export const createResolvablePromise = (
2 | data: T
3 | ): { promise: Promise; resolve: () => void } => {
4 | let resolve: (data: T) => void;
5 | return {
6 | promise: new Promise((resolveArg) => {
7 | resolve = resolveArg;
8 | }),
9 | resolve: () => resolve(data),
10 | };
11 | };
12 |
--------------------------------------------------------------------------------
/packages/testing/currentApiKeyMock.ts:
--------------------------------------------------------------------------------
1 | export const currentApiKeyMock = {
2 | id: 42,
3 | key: 'asdfasdsfasdfasdfasdf',
4 | username: 'john@toe@tolgee.com',
5 | userFullName: 'John Doe',
6 | projectId: 15,
7 | projectName: 'Tolgee test',
8 | scopes: [
9 | 'screenshots.view',
10 | 'screenshots.upload',
11 | 'screenshots.delete',
12 | 'keys.edit',
13 | 'translations.edit',
14 | 'translations.view',
15 | ],
16 | };
17 |
--------------------------------------------------------------------------------
/packages/testing/fetchMock.ts:
--------------------------------------------------------------------------------
1 | import fetchMock from 'jest-fetch-mock';
2 | import { getMocker } from './mockData';
3 |
4 | export const mockCoreFetch = () => {
5 | const asyncFetchResult = mockCoreFetchAsync();
6 | asyncFetchResult.resolveAll();
7 | return asyncFetchResult.fetch;
8 | };
9 |
10 | export const mockCoreFetchAsync = () => {
11 | const mocker = getMocker();
12 |
13 | const fetch = fetchMock.mockResponse((req) => {
14 | return mocker.getDataForUrl(req.url);
15 | });
16 |
17 | return { ...mocker.mockData, fetch, resolveAll: mocker.resolveAll };
18 | };
19 |
--------------------------------------------------------------------------------
/packages/testing/index.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tolgee/tolgee-js/ea8ffc97dcfec4a1ea7b06abde18d35e208cfe91/packages/testing/index.ts
--------------------------------------------------------------------------------
/packages/testing/mockTranslations.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | en: {
3 | hello_world: 'Hello world!',
4 | peter_dogs: 'Peter has {dogsCount} dogs.',
5 | english_fallback: 'English fallback',
6 | with_tags: 'This text is formatted',
7 | with_tag: 'bold',
8 | },
9 | 'en:test': {
10 | test: 'English test',
11 | test_english_fallback: 'Test english fallback',
12 | },
13 | cs: {
14 | hello_world: 'Ahoj světe!',
15 | peter_dogs: 'Petr má {dogsCount} psů.',
16 | with_tags: 'Tento text je formátovaný',
17 | with_tag: 'bold',
18 | },
19 | 'cs:test': {
20 | test: 'Český test',
21 | },
22 | 'en:fallback': {
23 | fallback: 'Fallback fallback',
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/packages/testing/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@tolgee/testing",
3 | "version": "6.2.5",
4 | "description": "Shared testing tools",
5 | "main": "index.ts",
6 | "private": true,
7 | "keywords": [],
8 | "author": "Tolgee",
9 | "license": "ISC"
10 | }
11 |
--------------------------------------------------------------------------------
/packages/testing/wait.ts:
--------------------------------------------------------------------------------
1 | export const wait = (durationInMs: number) =>
2 | new Promise((resolve) => {
3 | setTimeout(() => {
4 | resolve();
5 | }, durationInMs);
6 | });
7 |
--------------------------------------------------------------------------------
/packages/vue/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | /lib
5 | /coverage
6 |
7 |
8 | # local env files
9 | .env.local
10 | .env.*.local
11 |
12 | # Log files
13 | npm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 | pnpm-debug.log*
17 |
18 | # Editor directories and files
19 | .idea
20 | .vscode
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw?
--------------------------------------------------------------------------------
/packages/vue/jest.config.mjs:
--------------------------------------------------------------------------------
1 | export default {
2 | preset: 'ts-jest',
3 | testEnvironment: 'jsdom',
4 | unmockedModulePathPatterns: ['/node_modules/*'],
5 | modulePathIgnorePatterns: ['cypress'],
6 | transformIgnorePatterns: ['node_modules/(?!@tolgee/core)'],
7 | moduleFileExtensions: ['js', 'ts', 'tsx', 'json', 'vue'],
8 | transform: {
9 | '^.+\\.vue$': '@vue/vue3-jest',
10 | },
11 | testEnvironmentOptions: {
12 | customExportConditions: ['node', 'node-addons'],
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/packages/vue/src/GlobalContextPlugin.ts:
--------------------------------------------------------------------------------
1 | import type { TolgeePlugin } from '@tolgee/web';
2 | import type { TolgeeVueContext } from './types';
3 |
4 | let globalContext: TolgeeVueContext | undefined;
5 |
6 | export const GlobalContextPlugin = (): TolgeePlugin => (tolgee) => {
7 | globalContext = {
8 | tolgee,
9 | isInitialRender: false,
10 | };
11 | return tolgee;
12 | };
13 |
14 | export function getGlobalContext() {
15 | return globalContext;
16 | }
17 |
--------------------------------------------------------------------------------
/packages/vue/src/index.ts:
--------------------------------------------------------------------------------
1 | export { TolgeeProvider } from './TolgeeProvider';
2 | export { T } from './T';
3 | export { useTolgee } from './useTolgee';
4 | export { useTranslate } from './useTranslate';
5 | export { GlobalContextPlugin } from './GlobalContextPlugin';
6 | export { VueTolgee } from './VueTolgee';
7 | export * from './types';
8 |
9 | export * from '@tolgee/web';
10 |
--------------------------------------------------------------------------------
/packages/vue/src/mocks/ComponentUsingProvider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ tolgeeContext.tolgee.getLanguage() }}
4 |
5 |
6 |
7 |
13 |
--------------------------------------------------------------------------------
/packages/vue/src/mocks/ProviderComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | It's rendered!
4 |
5 |
6 |
7 |
23 |
--------------------------------------------------------------------------------
/packages/vue/src/mocks/ProviderComponentSlot.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | It's rendered!
4 | loading
5 |
6 |
7 |
23 |
--------------------------------------------------------------------------------
/packages/vue/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | declare module '*.vue' {
3 | import type { DefineComponent } from 'vue'
4 | const component: DefineComponent<{}, {}, any>
5 | export default component
6 | }
7 |
--------------------------------------------------------------------------------
/packages/vue/src/types.ts:
--------------------------------------------------------------------------------
1 | import { TolgeeInstance } from '@tolgee/web';
2 |
3 | export type TolgeeVueContext = {
4 | tolgee: TolgeeInstance;
5 | isInitialRender: boolean;
6 | };
7 |
--------------------------------------------------------------------------------
/packages/vue/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2017",
4 | "module": "esnext",
5 | "rootDir": "src",
6 | "sourceMap": true,
7 | "declaration": true,
8 | "outDir": "./lib",
9 | "moduleResolution": "node",
10 | "skipLibCheck": true,
11 | "lib": ["es2018", "es2020", "dom"],
12 | "experimentalDecorators": true,
13 | "emitDecoratorMetadata": true,
14 | "jsx": "preserve",
15 | "downlevelIteration": true,
16 | "emitDeclarationOnly": true,
17 | "types": ["node", "jest", "@types/jest"],
18 | "paths": {
19 | "@/*": ["./*"]
20 | },
21 | "esModuleInterop": true
22 | },
23 | "include": ["src"],
24 | "exclude": ["node_modules"]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/vue/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "include": ["src/index.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/web/.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 | lib
11 | coverage
12 |
13 | node_modules
14 | dist
15 | dist-ssr
16 | *.local
17 |
18 | # Editor directories and files
19 | .vscode/*
20 | !.vscode/extensions.json
21 | .idea
22 | .DS_Store
23 | *.suo
24 | *.ntvs*
25 | *.njsproj
26 | *.sln
27 | *.sw?
28 |
--------------------------------------------------------------------------------
/packages/web/index.cjs:
--------------------------------------------------------------------------------
1 | module.exports =
2 | process.env.NODE_ENV === 'production'
3 | ? require('./dist/tolgee-web.production.umd.cjs')
4 | : require('./dist/tolgee-web.development.umd.cjs');
5 |
--------------------------------------------------------------------------------
/packages/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/web/jest.config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | preset: 'ts-jest',
3 | testEnvironment: 'jsdom',
4 | transformIgnorePatterns: ['/node_modules/(?!@tolgee)', '^.+\\.js$'],
5 | moduleNameMapper: {
6 | '@testFixtures/(.*)': '/src/__testFixtures/$1',
7 | },
8 | roots: ['src'],
9 | };
10 |
--------------------------------------------------------------------------------
/packages/web/public/i18n/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/packages/web/public/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/packages/web/public/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/packages/web/public/i18n/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/packages/web/public/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/packages/web/src/app/App.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import { useTolgee } from './basicTolgee';
3 |
4 | import { Todos } from './Todos';
5 | import { TranslationMethods } from './TranslationMethods';
6 |
7 | export const App = () => {
8 | const currentRoute = window.location.pathname;
9 | const tolgee = useTolgee(['initialLoad']);
10 |
11 | useEffect(() => {
12 | tolgee.run();
13 | }, []);
14 |
15 | if (!tolgee.isLoaded()) {
16 | return null;
17 | }
18 |
19 | return (
20 | <>
21 | {currentRoute === '/translation-methods' ? (
22 |
23 | ) : (
24 |
25 | )}
26 | >
27 | );
28 | };
29 |
--------------------------------------------------------------------------------
/packages/web/src/app/components/LangSelector.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useTolgee } from '../basicTolgee';
3 |
4 | export const LangSelector: React.FC = () => {
5 | const tolgee = useTolgee(['pendingLanguage']);
6 |
7 | return (
8 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/web/src/app/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import { LangSelector } from './LangSelector';
2 |
3 | export const Navbar = ({ children }: React.PropsWithChildren) => {
4 | return (
5 |
6 | {children}
7 |
8 |
9 | );
10 | };
11 |
--------------------------------------------------------------------------------
/packages/web/src/app/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import { App } from './App.tsx';
4 | import './style.css';
5 |
6 | ReactDOM.createRoot(document.getElementById('root')!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/packages/web/src/app/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/packages/web/src/package/BrowserExtensionPlugin/constants.ts:
--------------------------------------------------------------------------------
1 | export const IN_CONTEXT_FILE = 'tolgee-in-context-tools.umd.min.js';
2 | export const IN_CONTEXT_UMD_NAME = '@tolgee/in-context-tools';
3 | export const IN_CONTEXT_EXPORT_NAME = 'InContextTools';
4 |
--------------------------------------------------------------------------------
/packages/web/src/package/ContextUi.ts:
--------------------------------------------------------------------------------
1 | import { TolgeePlugin, UiMiddleware } from '@tolgee/core';
2 | import { isSSR } from './tools/isSSR';
3 | import { InContextUi } from './ui/InContextUi';
4 |
5 | export const ContextUi = (): TolgeePlugin => (tolgee, tools) => {
6 | let ui: UiMiddleware | undefined = undefined;
7 |
8 | if (!isSSR()) {
9 | ui = (props) => InContextUi(props);
10 | }
11 | tools.setUi(ui);
12 | return tolgee;
13 | };
14 |
--------------------------------------------------------------------------------
/packages/web/src/package/InContextTools.ts:
--------------------------------------------------------------------------------
1 | import type { TolgeePlugin } from '@tolgee/core';
2 | import { ContextUi } from './ContextUi';
3 | import { DevBackend } from './DevBackend';
4 | import { InContextOptions } from './types';
5 | import { ObserverPlugin } from './ObserverPlugin';
6 |
7 | export const InContextTools =
8 | (props?: InContextOptions): TolgeePlugin =>
9 | (tolgee, tools) => {
10 | const { credentials } = props || {};
11 | tolgee.addPlugin(DevBackend());
12 | if (!tools.hasUi()) {
13 | tolgee.addPlugin(ContextUi());
14 | }
15 | if (!tools.hasObserver()) {
16 | tolgee.addPlugin(ObserverPlugin());
17 | }
18 | if (credentials) {
19 | tolgee.overrideCredentials(credentials);
20 | }
21 | return tolgee;
22 | };
23 |
--------------------------------------------------------------------------------
/packages/web/src/package/InvisibleObserver.ts:
--------------------------------------------------------------------------------
1 | import type { ObserverMiddleware, ObserverRunProps } from '@tolgee/core';
2 | import { GeneralObserver } from './observers/general/GeneralObserver';
3 | import { InvisibleWrapper } from './observers/invisible/InvisibleWrapper';
4 |
5 | export const InvisibleObserver = (): ObserverMiddleware => () => {
6 | const observer = GeneralObserver();
7 |
8 | const self = Object.freeze({
9 | ...observer,
10 | run(props: ObserverRunProps) {
11 | const wrapper = InvisibleWrapper({
12 | fullKeyEncode: props.options.fullKeyEncode,
13 | });
14 | observer.run({ ...props, wrapper });
15 | },
16 | retranslate() {},
17 | outputNotFormattable: false,
18 | });
19 | return self;
20 | };
21 |
--------------------------------------------------------------------------------
/packages/web/src/package/ObserverPlugin.ts:
--------------------------------------------------------------------------------
1 | import { TolgeePlugin } from '@tolgee/core';
2 | import { InvisibleObserver } from './InvisibleObserver';
3 | import { TextObserver } from './TextObserver';
4 |
5 | export const ObserverPlugin = (): TolgeePlugin => (tolgee, tools) => {
6 | if (tolgee.getInitialOptions().observerType === 'text') {
7 | tools.setObserver(TextObserver());
8 | } else {
9 | tools.setObserver(InvisibleObserver());
10 | }
11 | return tolgee;
12 | };
13 |
--------------------------------------------------------------------------------
/packages/web/src/package/Tolgee.ts:
--------------------------------------------------------------------------------
1 | import { TolgeeCore, TolgeeChainer } from '@tolgee/core';
2 | import { BrowserExtensionPlugin } from './BrowserExtensionPlugin/BrowserExtensionPlugin';
3 |
4 | export function Tolgee(): TolgeeChainer {
5 | return TolgeeCore().use(BrowserExtensionPlugin());
6 | }
7 |
--------------------------------------------------------------------------------
/packages/web/src/package/__test__/observer.test.ts:
--------------------------------------------------------------------------------
1 | import { testObserver } from './testObserver';
2 | import { testRetranslate } from './testRetranslate';
3 |
4 | describe('invisble observer', () => {
5 | testObserver('invisible');
6 | });
7 |
8 | describe('text observer', () => {
9 | testObserver('text');
10 | testRetranslate('text');
11 | });
12 |
--------------------------------------------------------------------------------
/packages/web/src/package/entry-development.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-var-requires */
2 | export * from './entry-production';
3 | import { InContextTools } from './InContextTools';
4 |
5 | export const DevTools = InContextTools;
6 |
--------------------------------------------------------------------------------
/packages/web/src/package/entry-production.ts:
--------------------------------------------------------------------------------
1 | import { TolgeeInstance } from '@tolgee/core';
2 |
3 | export const DevTools = () => (tolgee: TolgeeInstance) => tolgee;
4 | export * from './typedIndex';
5 | export {
6 | PREFERRED_LANGUAGES_LOCAL_STORAGE_KEY,
7 | DEVTOOLS_ID,
8 | } from './constants';
9 |
--------------------------------------------------------------------------------
/packages/web/src/package/entry-tools.ts:
--------------------------------------------------------------------------------
1 | export { InContextTools } from './InContextTools';
2 | export { ContextUi } from './ContextUi';
3 |
--------------------------------------------------------------------------------
/packages/web/src/package/observers/general/ElementMeta.ts:
--------------------------------------------------------------------------------
1 | import type { KeyAndParams } from '@tolgee/core';
2 | import type { ElementMeta, NodeMeta, TolgeeElement } from '../../types';
3 |
4 | export function initElementMeta(element: TolgeeElement): ElementMeta {
5 | return {
6 | element,
7 | nodes: new Map(),
8 | };
9 | }
10 |
11 | export function initNodeMeta(
12 | oldTextContent: string,
13 | keys: KeyAndParams[]
14 | ): NodeMeta {
15 | return {
16 | oldTextContent,
17 | keys,
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/packages/web/src/package/observers/invisible/ValueMemory.ts:
--------------------------------------------------------------------------------
1 | export function ValueMemory() {
2 | const values: string[] = [];
3 |
4 | return Object.freeze({
5 | valueToNumber(key: string) {
6 | let index = values.indexOf(key);
7 | if (index === -1) {
8 | index = values.length;
9 | values.push(key);
10 | }
11 | return index;
12 | },
13 |
14 | numberToValue(num: number) {
15 | return values[num];
16 | },
17 | });
18 | }
19 |
20 | export type ValueMemoryInstance = ReturnType;
21 |
--------------------------------------------------------------------------------
/packages/web/src/package/tools/decodeApiKey.test.ts:
--------------------------------------------------------------------------------
1 | import { getProjectIdFromApiKey } from './decodeApiKey';
2 |
3 | const PAK_KEY = 'tgpak_gfpxm4lin4zdazleoq4gm2rumfxgi2lfom2gw4dpguzxc';
4 | const OLD_KEY = 'ryj4psai6vetel5b27ven6fajf';
5 |
6 | describe('get projectId from api key', () => {
7 | it('can decode from pak key', () => {
8 | expect(getProjectIdFromApiKey(PAK_KEY)).toEqual(1);
9 | });
10 |
11 | it("won't fail on legacy code", () => {
12 | expect(getProjectIdFromApiKey(OLD_KEY)).toBeUndefined();
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/packages/web/src/package/tools/detectLanguageFromHeaders.ts:
--------------------------------------------------------------------------------
1 | import { detectLanguage } from '../LanguageDetector';
2 | import { getHeaderLanguages } from './getHeaderLanguages';
3 |
4 | export const detectLanguageFromHeaders = (
5 | headers: Headers,
6 | availableLanguages: string[]
7 | ) => {
8 | const languages = getHeaderLanguages(headers);
9 | return languages[0] && detectLanguage(languages[0], availableLanguages);
10 | };
11 |
--------------------------------------------------------------------------------
/packages/web/src/package/tools/getHeaderLanguages.ts:
--------------------------------------------------------------------------------
1 | export function getHeaderLanguages(headers: Headers) {
2 | const acceptLanguageHeader = headers.get('Accept-Language');
3 | if (!acceptLanguageHeader) {
4 | return [];
5 | }
6 | // Split the header into locales based on commas
7 | const locales = acceptLanguageHeader.split(',').map((locale) => {
8 | // Remove whitespace and split by ';' to get only the locale part
9 | const [localePart] = locale.trim().split(';');
10 | return localePart;
11 | });
12 |
13 | // Filter out any empty strings and return the unique locales
14 | return [...new Set(locales.filter((locale) => locale && locale !== '*'))];
15 | }
16 |
--------------------------------------------------------------------------------
/packages/web/src/package/tools/isSSR.ts:
--------------------------------------------------------------------------------
1 | export function isSSR() {
2 | return typeof globalThis.window?.document?.createElement === 'undefined';
3 | }
4 |
5 | export function throwIfSSR(origin: string) {
6 | if (isSSR()) {
7 | throw new Error(`${origin}: Can't run on the server`);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/web/src/package/tools/url.test.ts:
--------------------------------------------------------------------------------
1 | import { joinUrls } from './url';
2 |
3 | describe('url module', () => {
4 | it('joins urls without double slash', () => {
5 | expect(joinUrls('a/b/', '/c')).toEqual('a/b/c');
6 | });
7 |
8 | it("doesn't remove last slash", () => {
9 | expect(joinUrls('a/b/', '/c/')).toEqual('a/b/c/');
10 | });
11 |
12 | it("doesn't touch the protocol", () => {
13 | expect(joinUrls('https://test.com/', '/c/')).toEqual('https://test.com/c/');
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/packages/web/src/package/tools/url.ts:
--------------------------------------------------------------------------------
1 | function composeUrl(base: string, path: string): string {
2 | // Ensure the base URL does not end with a slash
3 | base = base.replace(/\/+$/, '');
4 | // Ensure the path does not start with a slash
5 | path = path.replace(/^\/+/, '');
6 | // Combine the two parts with a single slash in between
7 | return `${base}/${path}`;
8 | }
9 |
10 | export function joinUrls(...parts: string[]): string {
11 | let result = parts[0];
12 | parts.slice(1).forEach((part) => {
13 | result = composeUrl(result, part);
14 | });
15 | return result;
16 | }
17 |
18 | export function createUrl(...parts: string[]): URL {
19 | const base =
20 | typeof window === 'undefined' ? undefined : window.location.origin;
21 | return new URL(joinUrls(...parts), base);
22 | }
23 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/KeyDialog/Link.tsx:
--------------------------------------------------------------------------------
1 | import { OpenInNew } from '@mui/icons-material';
2 | import { styled } from '@mui/material';
3 |
4 | type Props = {
5 | href: string;
6 | children: React.ReactNode;
7 | };
8 |
9 | const StyledLink = styled('a')``;
10 |
11 | const StyledIcon = styled(OpenInNew)`
12 | width: 17px;
13 | height: 17px;
14 | position: relative;
15 | top: 3px;
16 | margin-left: 1px;
17 | `;
18 |
19 | export const NewTabLink = ({ href, children }: Props) => {
20 | return (
21 |
22 | {children}
23 |
24 |
25 | );
26 | };
27 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/KeyDialog/ScreenshotGallery/utils.ts:
--------------------------------------------------------------------------------
1 | export const MAX_FILE_COUNT = 20;
2 |
3 | export const dataTransferItemsToArray = (
4 | items: DataTransferItemList
5 | ): File[] => {
6 | const result = [] as any[];
7 | for (let i = 0; i < items.length; i++) {
8 | if (items[i].kind === 'file') {
9 | result.push(items[i].getAsFile());
10 | }
11 | }
12 | return result;
13 | };
14 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/KeyDialog/Tags/CloseButton.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@mui/material';
3 | import { Close } from '@mui/icons-material';
4 |
5 | const StyledCloseIcon = styled(Close)`
6 | font-size: 20px;
7 | cursor: pointer;
8 | padding: 2px;
9 | `;
10 |
11 | type Props = {
12 | onClick?: React.MouseEventHandler;
13 | };
14 |
15 | export const CloseButton: React.FC = ({ onClick }) => {
16 | return (
17 |
22 | );
23 | };
24 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/KeyDialog/TranslationDialog.tsx:
--------------------------------------------------------------------------------
1 | import { TranslationDialogWrapper } from './TranslationDialogWrapper';
2 | import { KeyForm } from './KeyForm';
3 | import { ThemeProvider } from '../ThemeProvider';
4 |
5 | export const TranslationDialog = () => {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/KeyDialog/editor/editorTheme.ts:
--------------------------------------------------------------------------------
1 | export const editorTheme = {
2 | variable: {
3 | border: '#7AD3C1',
4 | background: '#BEF3E9',
5 | text: '#008371',
6 | },
7 | tag: {
8 | border: '#F27FA6',
9 | background: '#F9C4D6',
10 | text: '#822343',
11 | },
12 | variant: {
13 | border: '#BBC2CB',
14 | background: '#F0F2F4',
15 | text: '#4D5B6E',
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/KeyDialog/languageHelpers.ts:
--------------------------------------------------------------------------------
1 | import { components } from '../client/apiSchema.generated';
2 |
3 | type LanguageModel = components['schemas']['LanguageModel'];
4 |
5 | export const putBaseLangFirst = (languages: LanguageModel[] | undefined) => {
6 | const base = languages?.find((l) => l.base);
7 | if (base) {
8 | return [base, ...(languages || []).filter((val) => val !== base)];
9 | }
10 | return languages;
11 | };
12 |
13 | export const putBaseLangFirstTags = (strings: Array, base?: string) => {
14 | if (base && strings.includes(base)) {
15 | return [base, ...strings.filter((val) => val !== base)];
16 | }
17 | return strings;
18 | };
19 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/common/FieldTitle.tsx:
--------------------------------------------------------------------------------
1 | import { styled } from '@mui/material';
2 | import { HTMLFactory } from 'react';
3 |
4 | export const ScFieldTitle = styled('div')`
5 | display: flex;
6 | margin-top: 16px;
7 | margin-bottom: 4px;
8 | font-size: 14px;
9 | color: ${({ theme }) => theme.palette.text.secondary};
10 | justify-content: space-between;
11 | ` as unknown as HTMLFactory;
12 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/common/Tooltip.tsx:
--------------------------------------------------------------------------------
1 | import { Tooltip as TooltipMui } from '@mui/material';
2 | import { DEVTOOLS_Z_INDEX } from '../../constants';
3 | import { getRootElement } from '../getRootElement';
4 |
5 | type Props = React.ComponentProps;
6 |
7 | export const Tooltip = (props: Props) => {
8 | return (
9 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/screenshots/ScreenshotPreview.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@mui/material';
3 |
4 | const Img = styled('img')`
5 | width: 100px;
6 | height: 100px;
7 | object-fit: contain;
8 | padding: 2px;
9 | box-sizing: 'border-box';
10 | `;
11 |
12 | type Props = {
13 | url: string;
14 | };
15 |
16 | export const ScreenshotPreview: React.FC = ({ url }) => {
17 | return
;
18 | };
19 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/tools/checkPlatformVersion.ts:
--------------------------------------------------------------------------------
1 | const SEMVER_REGEX = /^v[0-9]+\.[0-9]+\.[0-9]+$/;
2 |
3 | export const checkPlatformVersion = (
4 | requiredV: string,
5 | currentV: string | undefined
6 | ) => {
7 | if (!currentV || !SEMVER_REGEX.test(currentV)) {
8 | return undefined;
9 | }
10 | const result = requiredV.localeCompare(currentV, 'en', {
11 | numeric: true,
12 | sensitivity: 'base',
13 | });
14 |
15 | if (result > 0) {
16 | return new Error(
17 | `Requires minimal platform version ${requiredV} (got ${currentV})`
18 | );
19 | }
20 | return undefined;
21 | };
22 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/tools/isTranslationEmpty.ts:
--------------------------------------------------------------------------------
1 | import { TolgeeFormat } from '@tginternal/editor';
2 |
3 | export function isTranslationEmpty(
4 | value: TolgeeFormat | undefined,
5 | isPlural: boolean
6 | ) {
7 | if (!value) {
8 | return true;
9 | }
10 | if (isPlural) {
11 | return !Object.values(value.variants).join('');
12 | } else {
13 | return !value.variants.other;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/tools/permissions.ts:
--------------------------------------------------------------------------------
1 | export function isAuthorizedTo(scope: string, scopes: string[] | undefined) {
2 | return Boolean(scopes?.includes(scope));
3 | }
4 |
5 | export const isLanguagePermitted = (
6 | languageId: number | undefined,
7 | permittedLanguages: number[] | undefined
8 | ) => {
9 | if (!permittedLanguages?.length) {
10 | return true;
11 | }
12 | return permittedLanguages.includes(languageId as number);
13 | };
14 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/tools/sleep.ts:
--------------------------------------------------------------------------------
1 | export const sleep = (ms: number) =>
2 | new Promise((resolve) => setTimeout(resolve, ms));
3 |
--------------------------------------------------------------------------------
/packages/web/src/package/ui/tools/validateUrl.ts:
--------------------------------------------------------------------------------
1 | import { createUrl } from '../../tools/url';
2 |
3 | export function isUrlValid(url: string) {
4 | try {
5 | const result = createUrl(url);
6 | return result instanceof URL;
7 | } catch (e) {
8 | return false;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/web/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/packages/web/tools/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "internal": true,
3 | "main": "../dist/tolgee-in-context-tools.umd.cjs",
4 | "type": "module",
5 | "types": "../types/tools.d.ts",
6 | "exports": {
7 | ".": {
8 | "import": "./../dist/tolgee-in-context-tools.esm.js",
9 | "require": "./../dist/tolgee-in-context-tools.umd.cjs",
10 | "types": "./../types/tools.d.ts"
11 | },
12 | "./package.json": "./package.json"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/web/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2017",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | "esModuleInterop": true
18 |
19 | // /* Linting */
20 | // "strict": true,
21 | // "noUnusedLocals": true,
22 | // "noUnusedParameters": true,
23 | // "noFallthroughCasesInSwitch": true
24 | },
25 | "include": ["src"],
26 | "references": [{ "path": "./tsconfig.node.json" }]
27 | }
28 |
--------------------------------------------------------------------------------
/packages/web/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts", "*.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/packages/web/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "compilerOptions": {
4 | "allowArbitraryExtensions": true,
5 | "declaration": true,
6 | "emitDeclarationOnly": true,
7 | "noEmit": false,
8 | "rootDir": "src/package",
9 | "outDir": "./lib"
10 | },
11 | "include": ["src/package"],
12 | "exclude": ["./src/package/__test__"]
13 | }
--------------------------------------------------------------------------------
/packages/web/types/index.d.ts:
--------------------------------------------------------------------------------
1 | import type { TolgeePlugin } from '@tolgee/core';
2 | import type { InContextOptions } from '../lib/types';
3 |
4 | export declare const DevTools: (options?: InContextOptions) => TolgeePlugin;
5 |
6 | export * from '../lib/typedIndex';
7 |
--------------------------------------------------------------------------------
/packages/web/types/tools.d.ts:
--------------------------------------------------------------------------------
1 | import type { TolgeePlugin } from '@tolgee/core';
2 | import type { InContextOptions } from '../lib/types';
3 |
4 | export declare const ContextUi: () => TolgeePlugin;
5 | export declare const InContextTools: (
6 | options?: InContextOptions
7 | ) => TolgeePlugin;
8 |
--------------------------------------------------------------------------------
/packages/web/vite.config.production.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { buildPackage } from './rollup.common';
3 | import { createConfig } from './vite.config';
4 |
5 | export default createConfig({
6 | entry: resolve(__dirname, 'src/package/entry-production.ts'),
7 | rollupOptions: buildPackage({
8 | name: 'web',
9 | env: 'production',
10 | }),
11 | });
12 |
--------------------------------------------------------------------------------
/packages/web/vite.config.tools.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { buildPackage } from './rollup.common';
3 | import { createConfig } from './vite.config';
4 |
5 | export default createConfig({
6 | entry: resolve(__dirname, 'src/package/entry-tools.ts'),
7 | rollupOptions: buildPackage({
8 | name: 'in-context-tools',
9 | }),
10 | });
11 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/*'
3 | - 'packages/ngx/projects/ngx-tolgee'
4 | - 'testapps/*'
5 | - 'e2e'
6 |
--------------------------------------------------------------------------------
/scripts/cleanTurbo.js:
--------------------------------------------------------------------------------
1 | const { searchRecursively } = require('./searchRecursively');
2 | const fs = require('fs');
3 |
4 | const CACHE_FOLDER = 'node_modules/.cache/turbo';
5 |
6 | console.log('deleting', CACHE_FOLDER);
7 | fs.rmSync(CACHE_FOLDER, { recursive: true, force: true });
8 |
9 | const files = searchRecursively('.', '.turbo', [], 5);
10 |
11 | files.forEach((file) => {
12 | console.log('deleting', file);
13 | fs.rmSync(file, { recursive: true, force: true });
14 | });
15 |
--------------------------------------------------------------------------------
/scripts/customLinks.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 |
4 | // pnpm doesn't handle "publicConfig.directory" correctly
5 | // so when library uses separate package.json in build folder we need to redirect
6 | // symlink directly there
7 |
8 | {
9 | const target = './packages/ngx/dist/ngx-tolgee';
10 | const locationDir = './testapps/ngx/node_modules/@tolgee';
11 | const location = path.join(locationDir, 'ngx');
12 |
13 | if (fs.existsSync(location)) {
14 | fs.rmSync(location, { recursive: true, force: true });
15 | fs.symlinkSync(path.relative(locationDir, target), location);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/e2eRunner/serviceRunner/checkOutput.ts:
--------------------------------------------------------------------------------
1 | export const checkOutput = (output: string, regexOrString: string | RegExp) => {
2 | if (typeof output === 'string') {
3 | if (regexOrString instanceof RegExp) {
4 | if (output.match(regexOrString)) {
5 | return true;
6 | }
7 | } else if (typeof regexOrString == 'string') {
8 | if (output.includes(regexOrString)) {
9 | return true;
10 | }
11 | }
12 | }
13 | return false;
14 | };
15 |
--------------------------------------------------------------------------------
/scripts/e2eRunner/types.ts:
--------------------------------------------------------------------------------
1 | export type DockerComposeServiceConfig = {
2 | waitForOutput: string | RegExp;
3 | timeout?: number;
4 | stdErrEnabled?: boolean;
5 | };
6 |
7 | export type CommandLineServiceConfig = {
8 | command: string;
9 | cwd: string;
10 | waitForOutput?: string | RegExp;
11 | timeout?: number;
12 | environment?: Record;
13 | stdErrEnabled?: boolean;
14 | };
15 |
16 | export type TestDefinition = {
17 | dockerComposeServices?: Record;
18 | commandLineServices?: Record;
19 | };
20 |
21 | export type Config = {
22 | dockerComposeServices: Record;
23 | tests: Record;
24 | };
25 |
--------------------------------------------------------------------------------
/scripts/tolgeeUiVersion.js:
--------------------------------------------------------------------------------
1 | var pjson = require('../packages/web/package.json');
2 | console.log(pjson.version);
3 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/.env:
--------------------------------------------------------------------------------
1 | NEXT_PUBLIC_TOLGEE_API_URL=https://app.tolgee.io
2 | NEXT_PUBLIC_TOLGEE_API_KEY=
--------------------------------------------------------------------------------
/testapps/next-app-intl/.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 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 | /dist-e2e
19 |
20 | # misc
21 | .DS_Store
22 | *.pem
23 |
24 | # debug
25 | npm-debug.log*
26 | yarn-debug.log*
27 | yarn-error.log*
28 |
29 | # local env files
30 | .env*.local
31 |
32 | # vercel
33 | .vercel
34 |
35 | # typescript
36 | *.tsbuildinfo
37 | next-env.d.ts
38 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/README.md:
--------------------------------------------------------------------------------
1 | # Tolgee with next.js 14 app router DEMO
2 |
3 | This repo demonstrates how to use `tolgee` with new `next.js` app router.
4 |
5 | An example based on `next14` app folder with `tolgee` and `next-intl` package.
6 |
7 | ## Setup
8 |
9 | 1. Clone this repo
10 | 2. Run `npm i`
11 | 3. Run `npm run dev`
12 |
13 | ## Setup tolgee credentials (optional)
14 |
15 | 4. Create project in Tolgee platform
16 | 5. Add `.env.development.local` file to base folder of this project with an API key to your project
17 |
18 | ```
19 | NEXT_PUBLIC_TOLGEE_API_URL=https://app.tolgee.io
20 | NEXT_PUBLIC_TOLGEE_API_KEY=
21 | ```
22 |
23 | 6. Re-run `npm run dev`
24 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/messages/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next-app-intl/messages/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next-app-intl/messages/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next-app-intl/messages/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next-app-intl/next.config.js:
--------------------------------------------------------------------------------
1 | const createNextIntlPlugin = require('next-intl/plugin');
2 |
3 | const withNextIntl = createNextIntlPlugin();
4 |
5 | /** @type {import('next').NextConfig} */
6 | const nextConfig = {
7 | distDir: process.env.NEXT_BUILD_DIR || '.next',
8 | };
9 |
10 | module.exports = withNextIntl(nextConfig);
11 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@tolgee/next-app-intl-testapp",
3 | "version": "6.2.5",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "develop": "next dev",
8 | "build": "next build",
9 | "build:e2e": "NEXT_BUILD_DIR=dist-e2e next build",
10 | "start": "next start",
11 | "clean": "rm -rf .next dist-e2e"
12 | },
13 | "dependencies": {
14 | "@tolgee/format-icu": "6.2.5",
15 | "@tolgee/react": "6.2.5",
16 | "@tolgee/web": "6.2.5",
17 | "next": "15.1.0",
18 | "next-intl": "3.26.1",
19 | "react": "18.3.1",
20 | "react-dom": "18.3.1"
21 | },
22 | "devDependencies": {
23 | "@types/node": "^20",
24 | "@types/react": "^18.3.16",
25 | "@types/react-dom": "^18.3.5",
26 | "typescript": "^5.3.2"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tolgee/tolgee-js/ea8ffc97dcfec4a1ea7b06abde18d35e208cfe91/testapps/next-app-intl/public/favicon.ico
--------------------------------------------------------------------------------
/testapps/next-app-intl/public/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/app/[locale]/[...rest]/page.tsx:
--------------------------------------------------------------------------------
1 | import { notFound } from 'next/navigation';
2 |
3 | export default function CatchAllPage() {
4 | notFound();
5 | }
6 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/app/[locale]/page.tsx:
--------------------------------------------------------------------------------
1 | import { getTranslate } from '@/tolgee/server';
2 | import { Todos } from './Todos';
3 | import { Link } from '@/navigation';
4 |
5 | import { Navbar } from '@/components/Navbar';
6 |
7 | export default async function IndexPage() {
8 | const t = await getTranslate();
9 | return (
10 |
11 |
12 |
13 |
14 | {t('menu-item-translation-methods')}
15 |
16 |
17 |
18 |
19 | {t('app-title')}
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/app/[locale]/translation-methods/page.tsx:
--------------------------------------------------------------------------------
1 | import { Link } from '@/navigation';
2 | import { Navbar } from '@/components/Navbar';
3 |
4 | import { TranslationMethodsServer } from './TranslationMethodsServer';
5 | import { TranslationMethodsClient } from './TranslationMethodsClient';
6 |
7 | export default async function AboutPage() {
8 | return (
9 |
10 |
11 |
12 | The example app
13 |
14 |
15 |
16 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 | import './style.css';
3 |
4 | type Props = {
5 | children: ReactNode;
6 | };
7 |
8 | // Since we have a `not-found.tsx` page on the root, a layout file
9 | // is required, even if it's just passing children through.
10 | export default function RootLayout({ children }: Props) {
11 | return children;
12 | }
13 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/app/not-found.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import Error from 'next/error';
4 |
5 | // Render the default Next.js 404 page when a route
6 | // is requested that doesn't match the middleware and
7 | // therefore doesn't have a locale associated with it.
8 |
9 | export default function NotFound() {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import { redirect } from 'next/navigation';
2 |
3 | // This page only renders when the app is built statically (output: 'export')
4 | export default function RootPage() {
5 | redirect('/en');
6 | }
7 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { LangSelector } from './LangSelector';
3 |
4 | export const Navbar = ({ children }: React.PropsWithChildren) => {
5 | return (
6 |
7 | {children}
8 |
9 |
10 | );
11 | };
12 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/i18n/request.ts:
--------------------------------------------------------------------------------
1 | import { getRequestConfig } from 'next-intl/server';
2 |
3 | export default getRequestConfig(async ({ requestLocale }) => {
4 | const locale = await requestLocale;
5 | return {
6 | // do this to make next-intl not emmit any warnings
7 | messages: { locale: locale! },
8 | };
9 | });
10 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/middleware.ts:
--------------------------------------------------------------------------------
1 | import createMiddleware from 'next-intl/middleware';
2 | import { ALL_LANGUAGES, DEFAULT_LANGUAGE } from '@/tolgee/shared';
3 |
4 | // read more about next-intl middleware configuration
5 | // https://next-intl-docs.vercel.app/docs/routing/middleware#locale-prefix
6 | export default createMiddleware({
7 | locales: ALL_LANGUAGES,
8 | defaultLocale: DEFAULT_LANGUAGE,
9 | localePrefix: 'as-needed',
10 | });
11 |
12 | export const config = {
13 | // Skip all paths that should not be internationalized
14 | matcher: ['/((?!api|_next|.*\\..*).*)'],
15 | };
16 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/navigation.ts:
--------------------------------------------------------------------------------
1 | import { createNavigation } from 'next-intl/navigation';
2 | import { ALL_LANGUAGES } from './tolgee/shared';
3 |
4 | // read more about next-intl library
5 | // https://next-intl-docs.vercel.app
6 | export const { Link, redirect, usePathname, useRouter } = createNavigation({
7 | locales: ALL_LANGUAGES,
8 | });
9 |
--------------------------------------------------------------------------------
/testapps/next-app-intl/src/tolgee/server.tsx:
--------------------------------------------------------------------------------
1 | import { getLocale } from 'next-intl/server';
2 | import { createServerInstance } from '@tolgee/react/server';
3 | import { TolgeeBase } from './shared';
4 |
5 | export const { getTolgee, getTranslate, T } = createServerInstance({
6 | getLocale: getLocale,
7 | createTolgee: async (language) => {
8 | return TolgeeBase().init({
9 | observerOptions: {
10 | fullKeyEncode: true,
11 | },
12 | language,
13 | });
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/testapps/next-app/.env:
--------------------------------------------------------------------------------
1 | NEXT_PUBLIC_TOLGEE_API_URL=https://app.tolgee.io
2 | NEXT_PUBLIC_TOLGEE_API_KEY=
--------------------------------------------------------------------------------
/testapps/next-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 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 | /dist-e2e
19 |
20 | # misc
21 | .DS_Store
22 | *.pem
23 |
24 | # debug
25 | npm-debug.log*
26 | yarn-debug.log*
27 | yarn-error.log*
28 |
29 | # local env files
30 | .env*.local
31 |
32 | # vercel
33 | .vercel
34 |
35 | # typescript
36 | *.tsbuildinfo
37 | next-env.d.ts
38 |
--------------------------------------------------------------------------------
/testapps/next-app/messages/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next-app/messages/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next-app/messages/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next-app/messages/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next-app/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
6 |
--------------------------------------------------------------------------------
/testapps/next-app/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | distDir: process.env.NEXT_BUILD_DIR || '.next',
4 | };
5 |
6 | module.exports = nextConfig;
7 |
--------------------------------------------------------------------------------
/testapps/next-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@tolgee/next-app-testapp",
3 | "version": "6.2.5",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "develop": "next dev",
8 | "build": "next build",
9 | "build:e2e": "NEXT_BUILD_DIR=dist-e2e next build",
10 | "start": "next start",
11 | "clean": "rm -rf .next dist-e2e"
12 | },
13 | "dependencies": {
14 | "@tolgee/format-icu": "6.2.5",
15 | "@tolgee/react": "6.2.5",
16 | "@tolgee/web": "6.2.5",
17 | "next": "15.1.0",
18 | "react": "^18.3.1",
19 | "react-dom": "^18.3.1"
20 | },
21 | "devDependencies": {
22 | "@types/node": "^20",
23 | "@types/react": "^18.3.16",
24 | "@types/react-dom": "^18.3.5",
25 | "typescript": "^5.7.2"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/testapps/next-app/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tolgee/tolgee-js/ea8ffc97dcfec4a1ea7b06abde18d35e208cfe91/testapps/next-app/public/favicon.ico
--------------------------------------------------------------------------------
/testapps/next-app/public/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/next-app/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 | import { TolgeeNextProvider } from '@/tolgee/client';
3 | import { getTolgee } from '@/tolgee/server';
4 | import { getLanguage } from '@/tolgee/language';
5 | import './style.css';
6 |
7 | type Props = {
8 | children: ReactNode;
9 | };
10 |
11 | export default async function LocaleLayout({ children }: Props) {
12 | const language = await getLanguage();
13 | const tolgee = await getTolgee();
14 | const staticData = await tolgee.loadRequired();
15 |
16 | return (
17 |
18 |
19 |
20 | {children}
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/testapps/next-app/src/app/not-found.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import Error from 'next/error';
4 |
5 | // Render the default Next.js 404 page when a route
6 | // is requested that doesn't match the middleware and
7 | // therefore doesn't have a locale associated with it.
8 |
9 | export default function NotFound() {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/testapps/next-app/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import { getTranslate } from '@/tolgee/server';
2 |
3 | import { Navbar } from '@/components/Navbar';
4 | import Link from 'next/link';
5 | import { Todos } from './Todos';
6 |
7 | export default async function IndexPage() {
8 | const t = await getTranslate();
9 | return (
10 |
11 |
12 |
13 |
14 | {t('menu-item-translation-methods')}
15 |
16 |
17 |
18 |
19 | {t('app-title')}
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/testapps/next-app/src/app/translation-methods/page.tsx:
--------------------------------------------------------------------------------
1 | import { Navbar } from '@/components/Navbar';
2 |
3 | import { TranslationMethodsServer } from './TranslationMethodsServer';
4 | import { TranslationMethodsClient } from './TranslationMethodsClient';
5 | import Link from 'next/link';
6 |
7 | export default async function AboutPage() {
8 | return (
9 |
10 |
11 |
12 | The example app
13 |
14 |
15 |
16 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/testapps/next-app/src/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { LangSelector } from './LangSelector';
3 |
4 | export const Navbar = ({ children }: React.PropsWithChildren) => {
5 | return (
6 |
7 | {children}
8 |
9 |
10 | );
11 | };
12 |
--------------------------------------------------------------------------------
/testapps/next-app/src/tolgee/server.tsx:
--------------------------------------------------------------------------------
1 | import { getLanguage } from './language';
2 | import { TolgeeBase } from './shared';
3 | import { createServerInstance } from '@tolgee/react/server';
4 |
5 | export const { getTolgee, getTranslate, T } = createServerInstance({
6 | getLocale: getLanguage,
7 | createTolgee: async (language) => {
8 | return TolgeeBase().init({
9 | observerOptions: {
10 | fullKeyEncode: true,
11 | },
12 | language,
13 | });
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/testapps/next/.env:
--------------------------------------------------------------------------------
1 | NEXT_PUBLIC_TOLGEE_API_URL=https://app.tolgee.io
2 | NEXT_PUBLIC_TOLGEE_API_KEY=
--------------------------------------------------------------------------------
/testapps/next/.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 | /dist
17 | /dist-e2e
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env.local
30 | .env.development.local
31 | .env.test.local
32 | .env.production.local
33 |
34 | # vercel
35 | .vercel
--------------------------------------------------------------------------------
/testapps/next/messages/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next/messages/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next/messages/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next/messages/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/next/messages/namespaced/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Toto je klíč v namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/next/messages/namespaced/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Dies ist ein Schlüssel im Namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/next/messages/namespaced/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "This is a key in namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/next/messages/namespaced/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Ceci est une clé dans l'espace de noms"
3 | }
--------------------------------------------------------------------------------
/testapps/next/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
6 |
--------------------------------------------------------------------------------
/testapps/next/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | module.exports = {
3 | reactStrictMode: true,
4 | i18n: {
5 | locales: ['en', 'de', 'fr', 'cs'],
6 | localeDetection: false,
7 | defaultLocale: 'en',
8 | },
9 | distDir: process.env.NEXT_BUILD_DIR || '.next',
10 | };
11 |
--------------------------------------------------------------------------------
/testapps/next/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@tolgee/next-testapp",
3 | "version": "6.2.5",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "develop": "next dev",
8 | "build": "next build",
9 | "build:e2e": "NEXT_BUILD_DIR=dist-e2e next build",
10 | "clean": "rm -rf build build-e2e dist dist-e2e lib .next",
11 | "start": "next start",
12 | "lint": "next lint"
13 | },
14 | "dependencies": {
15 | "@tolgee/format-icu": "6.2.5",
16 | "@tolgee/react": "6.2.5",
17 | "next": "15.1.0",
18 | "react": "18.3.1",
19 | "react-dom": "18.3.1"
20 | },
21 | "devDependencies": {
22 | "@types/react": "18.3.16",
23 | "eslint": "8.57.0",
24 | "eslint-config-next": "13.2.3",
25 | "typescript": "4.9.5"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/testapps/next/public/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/next/src/components/LangSelector.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useRouter } from 'next/router';
3 |
4 | export const LangSelector: React.FC = () => {
5 | const router = useRouter();
6 | const setLanguage = (lang: string) => {
7 | router.replace(router.pathname, undefined, { locale: lang });
8 | };
9 |
10 | return (
11 |
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/testapps/next/src/components/Namespaces.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useTranslate, T } from '@tolgee/react';
3 |
4 | const Namespaces = () => {
5 | const { t } = useTranslate('namespaced');
6 |
7 | return (
8 |
9 |
10 |
t function with namespace
11 |
{t('this_is_a_key')}
12 |
13 |
14 |
15 |
t function with default namespace
16 |
{t('this_is_a_key', { ns: '' })}
17 |
18 |
19 |
20 |
T component with namespace
21 |
22 |
23 |
24 |
25 |
26 | );
27 | };
28 |
29 | export default Namespaces;
30 |
--------------------------------------------------------------------------------
/testapps/next/src/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import { LangSelector } from './LangSelector';
2 |
3 | export const Navbar = ({ children }: React.PropsWithChildren) => {
4 | return (
5 |
6 | {children}
7 |
8 |
9 | );
10 | };
11 |
--------------------------------------------------------------------------------
/testapps/next/src/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import Document, { Html, Head, Main, NextScript } from 'next/document';
2 |
3 | class MyDocument extends Document {
4 | render() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | );
16 | }
17 | }
18 |
19 | export default MyDocument;
20 |
--------------------------------------------------------------------------------
/testapps/next/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import { Todos } from '../views/Todos';
2 |
3 | const Page = () => {
4 | return ;
5 | };
6 |
7 | export default Page;
8 |
--------------------------------------------------------------------------------
/testapps/next/src/pages/translation-methods.tsx:
--------------------------------------------------------------------------------
1 | import { TranslationMethods } from '../views/TranslationMethods';
2 |
3 | const Page = () => {
4 | return ;
5 | };
6 |
7 | export default Page;
8 |
--------------------------------------------------------------------------------
/testapps/next/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "preserveSymlinks": true,
16 | "jsx": "preserve",
17 | "incremental": true
18 | },
19 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
20 | "exclude": ["node_modules"]
21 | }
22 |
--------------------------------------------------------------------------------
/testapps/ngx/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/testapps/ngx/.gitignore:
--------------------------------------------------------------------------------
1 | **/environment.stage.ts
2 | dist
3 | node_modules
4 | .angular
5 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/.browserslistrc:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | > 0.5%
9 | last 2 versions
10 | Firefox ESR
11 | not dead
12 | not IE 9-11 # For IE 9-11 support, remove 'not'.
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-root',
5 | templateUrl: './app.component.html',
6 | })
7 | export class AppComponent {
8 | constructor() {}
9 | }
10 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/component/lang-selector/lang-selector.component.html:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/component/lang-selector/lang-selector.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { TranslateService } from '@tolgee/ngx';
3 |
4 | @Component({
5 | selector: 'app-lang-selector',
6 | templateUrl: './lang-selector.component.html',
7 | })
8 | export class LangSelectorComponent implements OnInit {
9 | constructor(public translateService: TranslateService) {}
10 |
11 | ngOnInit(): void {}
12 | }
13 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/component/navbar/navbar.component.html:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/component/navbar/navbar.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-navbar',
5 | templateUrl: './navbar.component.html',
6 | })
7 | export class NavbarComponent implements OnInit {
8 | constructor() {}
9 |
10 | ngOnInit(): void {}
11 | }
12 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/lazy/lazy-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { LazyComponent } from './lazy.component';
4 |
5 | const routes: Routes = [{ path: '', component: LazyComponent }];
6 |
7 | @NgModule({
8 | imports: [RouterModule.forChild(routes)],
9 | exports: [RouterModule],
10 | })
11 | export class LazyRoutingModule {}
12 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/lazy/lazy.component.html:
--------------------------------------------------------------------------------
1 |
2 | The example app
3 |
4 |
5 |
6 |
Namespaced key
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/lazy/lazy.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-lazy',
5 | templateUrl: './lazy.component.html',
6 | })
7 | export class LazyComponent {
8 | constructor() {}
9 | }
10 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/lazy/lazy.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { LazyRoutingModule } from './lazy-routing.module';
5 | import { LazyComponent } from './lazy.component';
6 | import { NgxTolgeeModule } from '@tolgee/ngx';
7 |
8 | @NgModule({
9 | declarations: [LazyComponent],
10 | imports: [CommonModule, LazyRoutingModule, NgxTolgeeModule],
11 | })
12 | export class LazyModule {}
13 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/app/wait.ts:
--------------------------------------------------------------------------------
1 | export const wait = (durationInMs: number) =>
2 | new Promise((resolve) => {
3 | setTimeout(() => {
4 | resolve();
5 | }, durationInMs);
6 | });
7 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tolgee/tolgee-js/ea8ffc97dcfec4a1ea7b06abde18d35e208cfe91/testapps/ngx/projects/sampleapp/src/assets/.gitkeep
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/assets/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true,
3 | tolgeeApiKey: undefined,
4 | tolgeeApiUrl: undefined,
5 | };
6 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/i18n/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/i18n/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/i18n/namespaced/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Toto je klíč v namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/i18n/namespaced/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Dies ist ein Schlüssel im Namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/i18n/namespaced/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "This is a key in namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/i18n/namespaced/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Ceci est une clé dans l'espace de noms"
3 | }
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Angular + Tolgee Example App
6 |
7 |
8 |
9 |
10 | Loading...
11 |
12 |
13 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | function bootstrap() {
12 | platformBrowserDynamic()
13 | .bootstrapModule(AppModule)
14 | // eslint-disable-next-line no-console
15 | .catch((err) => console.error(err));
16 | }
17 |
18 | if (document.readyState === 'complete') {
19 | bootstrap();
20 | } else {
21 | document.addEventListener('DOMContentLoaded', bootstrap);
22 | }
23 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting,
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | // First, initialize the Angular testing environment.
11 | getTestBed().initTestEnvironment(
12 | BrowserDynamicTestingModule,
13 | platformBrowserDynamicTesting()
14 | );
15 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/app",
5 | "types": [
6 | "node"
7 | ]
8 | },
9 | "files": [
10 | "src/main.ts",
11 | "src/polyfills.ts"
12 | ],
13 | "include": [
14 | "src/**/*.d.ts"
15 | ],
16 | "exclude": [
17 | "src/test.ts",
18 | "src/**/*.spec.ts"
19 | ],
20 | }
21 |
--------------------------------------------------------------------------------
/testapps/ngx/projects/sampleapp/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/spec",
5 | "types": ["jasmine", "node"]
6 | },
7 | "files": ["src/test.ts", "src/polyfills.ts"],
8 | "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/testapps/ngx/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "downlevelIteration": true,
9 | "experimentalDecorators": true,
10 | "module": "es2020",
11 | "moduleResolution": "node",
12 | "importHelpers": true,
13 | "target": "ES2022",
14 | "resolveJsonModule": true,
15 | "typeRoots": [
16 | "node_modules/@types"
17 | ],
18 | "lib": [
19 | "es2018",
20 | "dom"
21 | ],
22 | "useDefineForClassFields": false
23 | },
24 | "angularCompilerOptions": {
25 | "fullTemplateTypeCheck": true,
26 | "strictInjectionParameters": true,
27 | "enableIvy": "ngtsc"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/testapps/react-i18next/.env:
--------------------------------------------------------------------------------
1 | VITE_APP_TOLGEE_API_URL=https://app.tolgee.io
2 | VITE_APP_TOLGEE_API_KEY=
--------------------------------------------------------------------------------
/testapps/react-i18next/.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 |
--------------------------------------------------------------------------------
/testapps/react-i18next/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/testapps/react-i18next/public/i18n/namespaced/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Toto je klíč v namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/react-i18next/public/i18n/namespaced/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Dies ist ein Schlüssel im Namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/react-i18next/public/i18n/namespaced/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "This is a key in namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/react-i18next/public/i18n/namespaced/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Ceci est une clé dans l'espace de noms"
3 | }
--------------------------------------------------------------------------------
/testapps/react-i18next/public/i18n/translation/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/react-i18next/public/i18n/translation/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/react-i18next/public/i18n/translation/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/react-i18next/public/i18n/translation/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/react-i18next/public/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/react-i18next/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tolgee/tolgee-js/ea8ffc97dcfec4a1ea7b06abde18d35e208cfe91/testapps/react-i18next/public/logo192.png
--------------------------------------------------------------------------------
/testapps/react-i18next/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tolgee/tolgee-js/ea8ffc97dcfec4a1ea7b06abde18d35e208cfe91/testapps/react-i18next/public/logo512.png
--------------------------------------------------------------------------------
/testapps/react-i18next/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/testapps/react-i18next/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/testapps/react-i18next/src/components/LangSelector.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useTranslation } from 'react-i18next';
3 |
4 | export const LangSelector: React.FC = () => {
5 | const { i18n } = useTranslation();
6 |
7 | return (
8 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/testapps/react-i18next/src/components/Namespaces.tsx:
--------------------------------------------------------------------------------
1 | import { useTranslation } from 'react-i18next';
2 |
3 | const Namespaces = () => {
4 | const { t } = useTranslation('namespaced');
5 |
6 | return (
7 |
8 |
9 |
t function with namespace
10 |
{t('this_is_a_key', { ns: 'namespaced' })}
11 |
12 |
13 |
14 |
t function with default namespace
15 |
{t('this_is_a_key', { ns: 'translation' })}
16 |
17 |
18 | );
19 | };
20 |
21 | export default Namespaces;
22 |
--------------------------------------------------------------------------------
/testapps/react-i18next/src/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import { LangSelector } from './LangSelector';
2 |
3 | export const Navbar = ({ children }: React.PropsWithChildren) => {
4 | return (
5 |
6 | {children}
7 |
8 |
9 | );
10 | };
11 |
--------------------------------------------------------------------------------
/testapps/react-i18next/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import { App } from './App.tsx';
4 | import './style.css';
5 |
6 | ReactDOM.createRoot(document.getElementById('root')!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/testapps/react-i18next/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/testapps/react-i18next/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/testapps/react-i18next/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/testapps/react-i18next/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | clearScreen: false,
8 | });
9 |
--------------------------------------------------------------------------------
/testapps/react/.env:
--------------------------------------------------------------------------------
1 | VITE_APP_TOLGEE_API_URL=https://app.tolgee.io
2 | VITE_APP_TOLGEE_API_KEY=
--------------------------------------------------------------------------------
/testapps/react/.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 |
--------------------------------------------------------------------------------
/testapps/react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/testapps/react/public/i18n/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/react/public/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/react/public/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/react/public/i18n/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/react/public/i18n/namespaced/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Toto je klíč v namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/react/public/i18n/namespaced/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Dies ist ein Schlüssel im Namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/react/public/i18n/namespaced/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "This is a key in namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/react/public/i18n/namespaced/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Ceci est une clé dans l'espace de noms"
3 | }
--------------------------------------------------------------------------------
/testapps/react/public/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/react/src/components/LangSelector.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useTolgee } from '@tolgee/react';
3 |
4 | export const LangSelector: React.FC = () => {
5 | const tolgee = useTolgee(['pendingLanguage']);
6 |
7 | return (
8 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/testapps/react/src/components/Namespaces.tsx:
--------------------------------------------------------------------------------
1 | import { useTranslate, T } from '@tolgee/react';
2 |
3 | export const Namespaces = () => {
4 | const { t } = useTranslate('namespaced');
5 |
6 | return (
7 |
8 |
9 |
t function with namespace
10 |
{t('this_is_a_key')}
11 |
12 |
13 |
14 |
t function with default namespace
15 |
{t('this_is_a_key', { ns: '' })}
16 |
17 |
18 |
19 |
T component with namespace
20 |
21 |
22 |
23 |
24 |
25 | );
26 | };
27 |
--------------------------------------------------------------------------------
/testapps/react/src/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import { LangSelector } from './LangSelector';
2 |
3 | export const Navbar = ({ children }: React.PropsWithChildren) => {
4 | return (
5 |
6 | {children}
7 |
8 |
9 | );
10 | };
11 |
--------------------------------------------------------------------------------
/testapps/react/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import { App } from './App.tsx';
4 | import './style.css';
5 |
6 | ReactDOM.createRoot(document.getElementById('root')!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/testapps/react/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/testapps/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/testapps/react/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/testapps/react/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | clearScreen: false,
8 | });
9 |
--------------------------------------------------------------------------------
/testapps/svelte/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | # Output
4 | .output
5 | .vercel
6 | .netlify
7 | .wrangler
8 | /.svelte-kit
9 | /build
10 |
11 | # OS
12 | .DS_Store
13 | Thumbs.db
14 |
15 | # Env
16 | .env
17 | .env.*
18 | !.env.example
19 | !.env.test
20 |
21 | # Vite
22 | vite.config.js.timestamp-*
23 | vite.config.ts.timestamp-*
24 |
--------------------------------------------------------------------------------
/testapps/svelte/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 |
--------------------------------------------------------------------------------
/testapps/svelte/src/app.d.ts:
--------------------------------------------------------------------------------
1 | // See https://svelte.dev/docs/kit/types#app.d.ts
2 | // for information about these interfaces
3 | declare global {
4 | namespace App {
5 | // interface Error {}
6 | // interface Locals {}
7 | // interface PageData {}
8 | // interface PageState {}
9 | // interface Platform {}
10 | }
11 | }
12 |
13 | export {};
14 |
--------------------------------------------------------------------------------
/testapps/svelte/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | %sveltekit.head%
9 |
10 |
11 | %sveltekit.body%
12 |
13 |
14 |
--------------------------------------------------------------------------------
/testapps/svelte/src/component/LangSelector.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
17 |
--------------------------------------------------------------------------------
/testapps/svelte/src/component/Namespaces.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 | {#if $isLoading}
7 | Loading namespace...
8 | {:else}
9 |
10 |
11 |
t function with namespace
12 |
{$t('this_is_a_key')}
13 |
14 |
15 |
16 |
t function with default namespace
17 |
{$t('this_is_a_key', { ns: '' })}
18 |
19 |
20 |
21 |
T component with namespace
22 |
23 |
24 |
25 |
26 |
27 | {/if}
28 |
--------------------------------------------------------------------------------
/testapps/svelte/src/component/Navbar.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | {@render menuItems?.()}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/testapps/svelte/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | // place files you want to import through the `$lib` alias in this folder.
2 |
--------------------------------------------------------------------------------
/testapps/svelte/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tolgee/tolgee-js/ea8ffc97dcfec4a1ea7b06abde18d35e208cfe91/testapps/svelte/static/favicon.png
--------------------------------------------------------------------------------
/testapps/svelte/static/i18n/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/svelte/static/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/svelte/static/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/svelte/static/i18n/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/svelte/static/i18n/namespaced/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Toto je klíč v namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/svelte/static/i18n/namespaced/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Dies ist ein Schlüssel im Namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/svelte/static/i18n/namespaced/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "This is a key in namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/svelte/static/i18n/namespaced/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Ceci est une clé dans l'espace de noms"
3 | }
--------------------------------------------------------------------------------
/testapps/svelte/static/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/svelte/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from '@sveltejs/adapter-auto';
2 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | // Consult https://svelte.dev/docs/kit/integrations
7 | // for more information about preprocessors
8 | preprocess: vitePreprocess(),
9 |
10 | kit: {
11 | // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
12 | // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
13 | // See https://svelte.dev/docs/kit/adapters for more information about adapters.
14 | adapter: adapter()
15 | }
16 | };
17 |
18 | export default config;
19 |
--------------------------------------------------------------------------------
/testapps/svelte/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "resolveJsonModule": true,
9 | "skipLibCheck": true,
10 | "sourceMap": true,
11 | "strict": true,
12 | "moduleResolution": "bundler"
13 | }
14 | // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
15 | // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
16 | //
17 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
18 | // from the referenced tsconfig.json - TypeScript does not merge them in
19 | }
20 |
--------------------------------------------------------------------------------
/testapps/svelte/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from '@sveltejs/kit/vite';
2 | import { defineConfig } from 'vite';
3 |
4 | export default defineConfig({
5 | plugins: [sveltekit()],
6 | clearScreen: false,
7 | });
8 |
--------------------------------------------------------------------------------
/testapps/vanilla/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | /lib
5 |
6 |
7 | # local env files
8 | .env.local
9 | .env.*.local
10 |
11 | # Log files
12 | npm-debug.log*
13 | yarn-debug.log*
14 | yarn-error.log*
15 | pnpm-debug.log*
16 |
17 | # Editor directories and files
18 | .idea
19 | .vscode
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
--------------------------------------------------------------------------------
/testapps/vanilla/apps/base/index.js:
--------------------------------------------------------------------------------
1 | import { Tolgee, DevTools, BackendFetch } from '@tolgee/web';
2 |
3 | const bundleDivElement = document.createElement('div');
4 |
5 | const tolgee = Tolgee()
6 | .use(DevTools())
7 | .use(BackendFetch({ prefix: 'i18n' }))
8 | .init({
9 | defaultLanguage: 'en',
10 | observerType: 'text',
11 | });
12 |
13 | document.body.append(bundleDivElement);
14 |
15 | const htmlParagraphElement = document.createElement('p');
16 |
17 | bundleDivElement.append(htmlParagraphElement);
18 |
19 | tolgee.run().then(() => {
20 | const translation = tolgee.t('test');
21 | htmlParagraphElement.append(translation);
22 | bundleDivElement.append('%-%tolgee:test%-%');
23 | });
24 |
--------------------------------------------------------------------------------
/testapps/vanilla/public/i18n/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "test": "Toto je text",
3 | "test_param": "Toto je text s parametrem: {param}."
4 | }
5 |
--------------------------------------------------------------------------------
/testapps/vanilla/public/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "test": "This is test text!",
3 | "test_param": "This is text with param: {param}.",
4 | "this_is_mentioned_just_in_english": "This is just in english.",
5 | "missing_in_current": "I am missing in current"
6 | }
7 |
--------------------------------------------------------------------------------
/testapps/vue-i18next/.env:
--------------------------------------------------------------------------------
1 | VUE_APP_TOLGEE_API_URL=https://app.tolgee.io
2 | VUE_APP_TOLGEE_API_KEY=
--------------------------------------------------------------------------------
/testapps/vue-i18next/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | /dist-e2e
5 |
6 |
7 | # local env files
8 | .env.local
9 | .env.*.local
10 |
11 | # Log files
12 | npm-debug.log*
13 | yarn-debug.log*
14 | yarn-error.log*
15 | pnpm-debug.log*
16 |
17 | # Editor directories and files
18 | .idea
19 | .vscode
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/testapps/vue-i18next/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/i18n/namespaced/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Toto je klíč v namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/i18n/namespaced/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Dies ist ein Schlüssel im Namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/i18n/namespaced/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "This is a key in namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/i18n/namespaced/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Ceci est une clé dans l'espace de noms"
3 | }
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/i18n/translation/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/i18n/translation/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/i18n/translation/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/i18n/translation/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/vue-i18next/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Tolgee vue i18next example
10 |
11 |
12 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/testapps/vue-i18next/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
26 |
--------------------------------------------------------------------------------
/testapps/vue-i18next/src/components/LangSelector.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
24 |
--------------------------------------------------------------------------------
/testapps/vue-i18next/src/components/Navbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
15 |
--------------------------------------------------------------------------------
/testapps/vue-i18next/src/i18n.js:
--------------------------------------------------------------------------------
1 | import {
2 | BackendFetch,
3 | DevTools,
4 | I18nextPlugin,
5 | Tolgee,
6 | withTolgee,
7 | } from '@tolgee/i18next';
8 | import i18next from 'i18next';
9 | import ICU from 'i18next-icu';
10 |
11 | export const tolgee = Tolgee()
12 | .use(DevTools())
13 | .use(BackendFetch())
14 | .use(I18nextPlugin())
15 | .init({
16 | apiUrl: process.env.VUE_APP_TOLGEE_API_URL,
17 | apiKey: process.env.VUE_APP_TOLGEE_API_KEY,
18 | });
19 |
20 | withTolgee(i18next, tolgee)
21 | .use(ICU)
22 | .init({
23 | lng: 'en', // or use i18next language detector
24 | supportedLngs: ['cs', 'en', 'fr', 'de'],
25 | });
26 |
27 | export { i18next };
28 |
--------------------------------------------------------------------------------
/testapps/vue-i18next/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import i18nextVue from 'i18next-vue';
3 |
4 | import { i18next } from './i18n';
5 | import App from './App.vue';
6 |
7 | createApp(App).use(i18nextVue, { i18next }).mount('#app');
8 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/.env:
--------------------------------------------------------------------------------
1 | VITE_APP_TOLGEE_API_URL=https://app.tolgee.io
2 | VITE_APP_TOLGEE_API_KEY=
--------------------------------------------------------------------------------
/testapps/vue-ssr/.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 | .DS_Store
12 | dist
13 | dist-ssr
14 | coverage
15 | *.local
16 |
17 | /cypress/videos/
18 | /cypress/screenshots/
19 |
20 | # Editor directories and files
21 | .vscode/*
22 | !.vscode/extensions.json
23 | .idea
24 | *.suo
25 | *.ntvs*
26 | *.njsproj
27 | *.sln
28 | *.sw?
29 |
30 | tsconfig.tsbuildinfo
31 |
32 | vite.config.ts.*
33 | tsconfig.tsbuildinfo
--------------------------------------------------------------------------------
/testapps/vue-ssr/components/LangSelector.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
23 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/components/Namespaces.vue:
--------------------------------------------------------------------------------
1 |
2 | Loading namespace...
3 |
4 |
5 |
t function with namespace
6 |
{{ t('this_is_a_key') }}
7 |
8 |
9 |
10 |
t function with default namespace
11 |
{{ t('this_is_a_key', { ns: '' }) }}
12 |
13 |
14 |
15 |
T component with namespace
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/components/Navbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
16 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/pages/+Layout.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/pages/+data.ts:
--------------------------------------------------------------------------------
1 | import { getServerLocales } from '../tolgee';
2 |
3 | export const data = async () => {
4 | const locales = await getServerLocales('en');
5 | return locales;
6 | };
7 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/pages/index/+Page.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/pages/translation-methods/+Page.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/public/i18n/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/vue-ssr/public/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/vue-ssr/public/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/vue-ssr/public/i18n/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}"
12 | }
--------------------------------------------------------------------------------
/testapps/vue-ssr/public/i18n/namespaced/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Toto je klíč v namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/vue-ssr/public/i18n/namespaced/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Dies ist ein Schlüssel im Namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/vue-ssr/public/i18n/namespaced/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "This is a key in namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/vue-ssr/public/i18n/namespaced/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Ceci est une clé dans l'espace de noms"
3 | }
--------------------------------------------------------------------------------
/testapps/vue-ssr/public/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/renderer/+config.ts:
--------------------------------------------------------------------------------
1 | import vikeVue from 'vike-vue/config';
2 |
3 | export default {
4 | extends: [vikeVue],
5 | passToClient: ['lang'],
6 | };
7 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/renderer/+onCreateApp.ts:
--------------------------------------------------------------------------------
1 | import { VueTolgee } from '@tolgee/vue';
2 | import { createTolgee } from '../tolgee';
3 |
4 | export const onCreateApp = (pageContext) => {
5 | const { app } = pageContext;
6 | const tolgee = createTolgee();
7 |
8 | app.use(VueTolgee, { tolgee, enableSSR: true });
9 | };
10 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/server/root.js:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-when-using-the-experimental-modules-flag/50052194#50052194
2 |
3 | import { dirname } from "path";
4 | import { fileURLToPath } from "url";
5 | const __dirname = dirname(fileURLToPath(import.meta.url));
6 | export const root = `${__dirname}/..`;
7 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@vue/tsconfig/tsconfig.node.json",
3 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
4 | "compilerOptions": {
5 | "composite": true,
6 | "types": ["node"],
7 | "skipLibCheck": true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/testapps/vue-ssr/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { fileURLToPath, URL } from 'node:url';
2 |
3 | import { defineConfig } from 'vite';
4 | import vue from '@vitejs/plugin-vue';
5 | import vueJsx from '@vitejs/plugin-vue-jsx';
6 | import vike from 'vike/plugin';
7 |
8 | // https://vitejs.dev/config/
9 | export default defineConfig({
10 | plugins: [vue(), vueJsx(), vike()],
11 | resolve: {
12 | alias: {
13 | '@': fileURLToPath(new URL('./src', import.meta.url)),
14 | },
15 | },
16 | clearScreen: false,
17 | });
18 |
--------------------------------------------------------------------------------
/testapps/vue/.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 | .DS_Store
12 | dist
13 | dist-ssr
14 | coverage
15 | *.local
16 |
17 | /cypress/videos/
18 | /cypress/screenshots/
19 |
20 | # Editor directories and files
21 | .vscode/*
22 | !.vscode/extensions.json
23 | .idea
24 | *.suo
25 | *.ntvs*
26 | *.njsproj
27 | *.sln
28 | *.sw?
29 |
--------------------------------------------------------------------------------
/testapps/vue/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import type { TFnType, TolgeeInstance } from '@tolgee/vue';
4 |
--------------------------------------------------------------------------------
/testapps/vue/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Vite App
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/testapps/vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@tolgee/vue-testapp",
3 | "version": "6.2.5",
4 | "private": true,
5 | "scripts": {
6 | "dev": "vite",
7 | "develop": "vite dev",
8 | "build": "run-p type-check build-only",
9 | "preview": "vite preview",
10 | "build-only": "vite build",
11 | "type-check": "vue-tsc --noEmit"
12 | },
13 | "dependencies": {
14 | "@tolgee/format-icu": "6.2.5",
15 | "@tolgee/vue": "6.2.5",
16 | "vue": "^3.2.45"
17 | },
18 | "devDependencies": {
19 | "@types/node": "^18.11.12",
20 | "@vitejs/plugin-vue": "^4.0.0",
21 | "@vitejs/plugin-vue-jsx": "^3.0.0",
22 | "@vue/tsconfig": "^0.1.3",
23 | "npm-run-all": "^4.1.5",
24 | "typescript": "~4.7.4",
25 | "vite": "^4.0.0",
26 | "vue-tsc": "^1.0.12"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/testapps/vue/public/i18n/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Přidat",
3 | "add-item-input-placeholder" : "Nová položka seznamu",
4 | "app-title" : "Co sbalit",
5 | "delete-item-button" : "Smazat",
6 | "menu-item-translation-methods" : "Metody překládání",
7 | "send-via-email" : "Odeslat e-mailem",
8 | "share-button" : "Sdílet",
9 | "this_is_a_key" : "Toto je klíč",
10 | "this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
11 | "this_is_a_key_with_tags" : "Toto je klíč s tagy bold {key}",
12 | "value": "hodnota"
13 | }
--------------------------------------------------------------------------------
/testapps/vue/public/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Einfügen",
3 | "add-item-input-placeholder" : "Neuer Eintrag",
4 | "app-title" : "Was mitnehmen",
5 | "delete-item-button" : "Löschen",
6 | "menu-item-translation-methods" : "Übersetzungsmethoden",
7 | "send-via-email" : "Per Email abschicken",
8 | "share-button" : "Teilen",
9 | "this_is_a_key" : "Dies ist ein Schlüssel",
10 | "this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
11 | "this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags bold {key}",
12 | "value": "Wert"
13 | }
--------------------------------------------------------------------------------
/testapps/vue/public/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Add",
3 | "add-item-input-placeholder" : "New list item",
4 | "app-title" : "What To Pack",
5 | "delete-item-button" : "Delete",
6 | "menu-item-translation-methods" : "Translation methods",
7 | "send-via-email" : "Send via e-mail",
8 | "share-button" : "Share",
9 | "this_is_a_key" : "This is a key",
10 | "this_is_a_key_with_params" : "This is key with params {key} {key2}",
11 | "this_is_a_key_with_tags" : "This is a key with tags bold {key}",
12 | "value": "value"
13 | }
--------------------------------------------------------------------------------
/testapps/vue/public/i18n/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "add-item-add-button" : "Ajouter",
3 | "add-item-input-placeholder" : "Nouveau élément de la liste",
4 | "app-title" : "Quoi emballer",
5 | "delete-item-button" : "Supprimer",
6 | "menu-item-translation-methods" : "Méthodes de la traduction",
7 | "send-via-email" : "Envoyer par e-mail",
8 | "share-button" : "Partager",
9 | "this_is_a_key" : "C'est un clé",
10 | "this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
11 | "this_is_a_key_with_tags" : "C'est la clé avec des tags bold {key}",
12 | "value": "valeur"
13 | }
--------------------------------------------------------------------------------
/testapps/vue/public/i18n/namespaced/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Toto je klíč v namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/vue/public/i18n/namespaced/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Dies ist ein Schlüssel im Namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/vue/public/i18n/namespaced/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "This is a key in namespace"
3 | }
--------------------------------------------------------------------------------
/testapps/vue/public/i18n/namespaced/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "this_is_a_key" : "Ceci est une clé dans l'espace de noms"
3 | }
--------------------------------------------------------------------------------
/testapps/vue/public/img/iconMail.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/testapps/vue/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Loading...
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
23 |
--------------------------------------------------------------------------------
/testapps/vue/src/components/LangSelector.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
23 |
--------------------------------------------------------------------------------
/testapps/vue/src/components/Namespaces.vue:
--------------------------------------------------------------------------------
1 |
2 | Loading namespace...
3 |
4 |
5 |
t function with namespace
6 |
{{ t('this_is_a_key') }}
7 |
8 |
9 |
10 |
t function with default namespace
11 |
{{ t('this_is_a_key', { ns: '' }) }}
12 |
13 |
14 |
15 |
T component with namespace
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
--------------------------------------------------------------------------------
/testapps/vue/src/components/Navbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
16 |
--------------------------------------------------------------------------------
/testapps/vue/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import App from './App.vue';
3 | import { Tolgee, DevTools, VueTolgee, BackendFetch } from '@tolgee/vue';
4 | import { FormatIcu } from '@tolgee/format-icu';
5 |
6 | const tolgee = Tolgee()
7 | .use(DevTools())
8 | .use(FormatIcu())
9 | .use(BackendFetch())
10 | .init({
11 | language: 'en',
12 | apiUrl: import.meta.env.VITE_TOLGEE_API_URL,
13 | apiKey: import.meta.env.VITE_TOLGEE_API_KEY,
14 | });
15 |
16 | const app = createApp(App);
17 |
18 | app.use(VueTolgee, { tolgee });
19 | app.mount('#app');
20 |
--------------------------------------------------------------------------------
/testapps/vue/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | declare module '*.vue' {
3 | import type { DefineComponent } from 'vue'
4 | const component: DefineComponent<{}, {}, any>
5 | export default component
6 | }
7 |
--------------------------------------------------------------------------------
/testapps/vue/tsconfig.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@vue/tsconfig/tsconfig.node.json",
3 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
4 | "compilerOptions": {
5 | "composite": true,
6 | "types": ["node"]
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/testapps/vue/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@vue/tsconfig/tsconfig.web.json",
3 | "include": ["env.d.ts", "src/**/*.ts", "src/**/*.vue"],
4 | "compilerOptions": {
5 | "allowJs": true,
6 | "baseUrl": ".",
7 | "paths": {
8 | "@/*": ["./src/*"]
9 | },
10 | },
11 |
12 | "references": [
13 | {
14 | "path": "./tsconfig.config.json"
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/testapps/vue/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { fileURLToPath, URL } from 'node:url';
2 |
3 | import { defineConfig } from 'vite';
4 | import vue from '@vitejs/plugin-vue';
5 | import vueJsx from '@vitejs/plugin-vue-jsx';
6 |
7 | // https://vitejs.dev/config/
8 | export default defineConfig({
9 | plugins: [vue(), vueJsx()],
10 | resolve: {
11 | alias: {
12 | '@': fileURLToPath(new URL('./src', import.meta.url)),
13 | },
14 | },
15 | clearScreen: false,
16 | });
17 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "jsx": "react",
4 | "esModuleInterop": true
5 | },
6 |
7 | }
--------------------------------------------------------------------------------