Skip to content

Commit

Permalink
feat: correctly initialize plural from default value in in-context fo…
Browse files Browse the repository at this point in the history
…rm (#3436)
  • Loading branch information
stepan662 authored Feb 25, 2025
1 parent 557e42b commit 6253348
Show file tree
Hide file tree
Showing 59 changed files with 856 additions and 2,577 deletions.
57 changes: 55 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ jobs:
NODE_AUTH_TOKEN: ${{secrets.TOLGEE_MACHINE_PAT}}

- id: set-dirs
run: echo "dirs=$(ls | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT
run: echo "dirs=$(ls | jq -R -s -c 'split("\n")[:-1] | map(select(. != "web-internal"))')" >> $GITHUB_OUTPUT
working-directory: e2e/cypress/e2e

outputs:
Expand Down Expand Up @@ -192,7 +192,60 @@ jobs:
working-directory: testapps/${{matrix.app}}

- name: Run e2e tests
run: pnpm run e2e run --headed ${{matrix.app}} --stdout prod,dev --skip-build
run: pnpm run e2e run --headed $(basename ${{matrix.app}}) --stdout prod,dev --skip-build

- uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress
path: |
e2e/cypress/videos/**/*
e2e/cypress/screenshots/**/*
cypress-web-internal:
name: E2e web-internal
needs: prepare
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: [18, 20]

steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}

- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
version: 8.15.9
run_install: false

- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: |
.pnpm-store/v3
~/.cache/Cypress
key: ${{ runner.os }}-pnpm-cypress-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-cypress-
- name: Install for root and for e2e
run: |
pnpm install --ignore-workspace
pnpm install --filter='./e2e'
- name: Build web package
run: |
pnpm build --filter="@tolgee/web"
- name: Run e2e tests
run: pnpm run e2e run --headed web-internal --stdout prod,dev --skip-build

- uses: actions/upload-artifact@v4
if: failure()
Expand Down
2 changes: 1 addition & 1 deletion e2e/cypress/common/devUiTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ export const getDevUiRoot = () => {
};

export const getDevUi = () => {
return getDevUiRoot().shadow();
return getDevUiRoot().shadow().find('div').first();
};
3 changes: 1 addition & 2 deletions e2e/cypress/common/nextInternalCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import { Scope } from './types';
export const openUI = (translation = 'What To Pack') => {
cy.contains(translation).should('be.visible').click({ altKey: true });
getDevUiRoot().should('exist');
getDevUi().contains(translation).should('be.visible');
getEditor().should('not.be.disabled');
cy.wait(300);
};

export const visitWithApiKey = (scopes: Scope[]) => {
createApiKey({ projectId: 1, scopes })
.then((data) => {
cy.visit(`http://localhost:8114/?api_key=${data.key}`);
cy.visit(`http://localhost:8114/translation-methods?api_key=${data.key}`);
})
.then(() =>
localStorage.setItem('__tolgee_preferredLanguages', '["en","de"]')
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,26 @@ context('UI with plurals', () => {
});
});

it('correctly detects plural from default value', () => {
cy.visit('http://localhost:8114/translation-methods');
openUI('2 items');
getDevUi().contains('Quick translation');
getDevUi().contains("(key doesn't exist yet)");
getDevUi()
.findDcy('key-plural-checkbox')
.find('input')
.should('be.checked');
getDevUi()
.findDcy('key-plural-variable-name')
.find('input')
.should('have.value', 'plural_value');
checkPluralValue('en', 'one', '#1 item');
checkPluralValue('en', 'other', '#10 items');
setPluralValue('cs', 'one', '# polozka');
setPluralValue('cs', 'few', '# polozky');
setPluralValue('cs', 'other', '# polozek');
});

function checkPluralValue(language: string, variant: string, text: string) {
getDevUi()
.findDcyWithCustom({
Expand Down
File renamed without changes.
File renamed without changes.
26 changes: 17 additions & 9 deletions e2e/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,29 @@

import 'cypress-real-events';

Cypress.Commands.add('closestDcy', { prevSubject: true }, (subject, dataCy) => {
return subject.closest('[data-cy="' + dataCy + '"]');
});
Cypress.Commands.add(
'closestDcy',
{ prevSubject: 'element' },
(subject, dataCy) => {
return cy.wrap(subject).closest(`[data-cy="${dataCy}"]`);
}
);

Cypress.Commands.add('gcy', (dataCy) => {
return cy.get('[data-cy="' + dataCy + '"]');
Cypress.Commands.add('gcy', (dataCy, options) => {
return cy.get('[data-cy="' + dataCy + '"]', options);
});

Cypress.Commands.add('findDcy', { prevSubject: true }, (subject, dataCy) => {
return subject.find('[data-cy="' + dataCy + '"]');
});
Cypress.Commands.add(
'findDcy',
{ prevSubject: 'element' },
(subject, dataCy) => {
return cy.wrap(subject).find(`[data-cy="${dataCy}"]`);
}
);

Cypress.Commands.add(
'findDcyWithCustom',
{ prevSubject: true },
{ prevSubject: 'element' },
(subject, { value, ...other }, options) =>
subject.find(
`[data-cy="${value}"]${Object.entries(other)
Expand Down
1 change: 1 addition & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"@testing-library/dom": "^9.3.4",
"@testing-library/jest-dom": "^6.4.2",
"@tginternal/editor": "^1.15.2",
"@tolgee/format-icu": "6.1.1",
"@types/jest": "^29.5.12",
"@types/react": "^18.3.16",
"@types/react-dom": "^18.3.5",
Expand Down
12 changes: 12 additions & 0 deletions packages/web/public/i18n/cs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"add-item-add-button" : "Přidat",
"add-item-input-placeholder" : "Nová položka seznamu",
"app-title" : "Co sbalit",
"delete-item-button" : "Smazat",
"menu-item-translation-methods" : "Metody překládání",
"send-via-email" : "Odeslat e-mailem",
"share-button" : "Sdílet",
"this_is_a_key" : "Toto je klíč",
"this_is_a_key_with_params" : "Toto je klíč s parametry {key} {key2}",
"this_is_a_key_with_tags" : "Toto je klíč s tagy <b>bold</b> <b><i>{key}</i></b>"
}
12 changes: 12 additions & 0 deletions packages/web/public/i18n/de.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"add-item-add-button" : "Einfügen",
"add-item-input-placeholder" : "Neuer Eintrag",
"app-title" : "Was mitnehmen",
"delete-item-button" : "Löschen",
"menu-item-translation-methods" : "Übersetzungsmethoden",
"send-via-email" : "Per Email abschicken",
"share-button" : "Teilen",
"this_is_a_key" : "Dies ist ein Schlüssel",
"this_is_a_key_with_params" : "Dies ist ein Schlüssel mit den Parametern {key} {key2}",
"this_is_a_key_with_tags" : "Dies ist ein Schlüssel mit den Tags <b>bold</b> <b><i>{key}</i></b>"
}
12 changes: 12 additions & 0 deletions packages/web/public/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"add-item-add-button" : "Add",
"add-item-input-placeholder" : "New list item",
"app-title" : "What To Pack",
"delete-item-button" : "Delete",
"menu-item-translation-methods" : "Translation methods",
"send-via-email" : "Send via e-mail",
"share-button" : "Share",
"this_is_a_key" : "This is a key",
"this_is_a_key_with_params" : "This is key with params {key} {key2}",
"this_is_a_key_with_tags" : "This is a key with tags <b>bold</b> <b><i>{key}</i></b>"
}
12 changes: 12 additions & 0 deletions packages/web/public/i18n/fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"add-item-add-button" : "Ajouter",
"add-item-input-placeholder" : "Nouveau élément de la liste",
"app-title" : "Quoi emballer",
"delete-item-button" : "Supprimer",
"menu-item-translation-methods" : "Méthodes de la traduction",
"send-via-email" : "Envoyer par e-mail",
"share-button" : "Partager",
"this_is_a_key" : "C'est un clé",
"this_is_a_key_with_params" : "C'est la clé avec paramètres {key} {key2}",
"this_is_a_key_with_tags" : "C'est la clé avec des tags <b>bold</b> <b><i>{key}</i></b>"
}
15 changes: 15 additions & 0 deletions packages/web/public/img/appLogo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions packages/web/public/img/background.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions packages/web/public/img/iconAdd.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions packages/web/public/img/iconMail.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions packages/web/public/img/iconShare.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/web/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 15 additions & 20 deletions packages/web/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,28 @@
import { useEffect } from 'react';
import { useTolgee } from './basicTolgee';
import { styled } from '@mui/material';

const StyledContainer = styled('div')`
margin: 100px auto;
max-width: 300px;
`;
import { Todos } from './Todos';
import { TranslationMethods } from './TranslationMethods';

export const App = () => {
const tolgee = useTolgee(['update', 'language']);
const currentRoute = window.location.pathname;
const tolgee = useTolgee(['initialLoad']);

useEffect(() => {
tolgee.run();
}, []);

if (!tolgee.isLoaded()) {
return null;
}

return (
<StyledContainer>
<div title="test">{tolgee.t('app-title')}</div>
<div>
{tolgee.t('app-title')}
{tolgee.t('add-item-input-placeholder')}
</div>
<button disabled>{tolgee.t('app-title')}</button>
<div style={{ pointerEvents: 'none' }}>
<div>{tolgee.t('app-title')}</div>
</div>
<div>
<div>{tolgee.t('new-key')}</div>
</div>
</StyledContainer>
<>
{currentRoute === '/translation-methods' ? (
<TranslationMethods />
) : (
<Todos />
)}
</>
);
};
Loading

0 comments on commit 6253348

Please sign in to comment.