Skip to content

Commit

Permalink
fix: Show plural all exact plural forms in the editor
Browse files Browse the repository at this point in the history
  • Loading branch information
JanCizmar committed Sep 4, 2024
1 parent ddbb4b5 commit 9c5b996
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 22 deletions.
23 changes: 22 additions & 1 deletion e2e/cypress/e2e/translations/plurals.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '../../common/translations';
import { waitForGlobalLoading } from '../../common/loading';
import { createKey, deleteProject } from '../../common/apiCalls/common';
import { confirmStandard } from '../../common/shared';
import { confirmStandard, gcyAdvanced } from '../../common/shared';

describe('Translations Base', () => {
let project: ProjectDTO = null;
Expand Down Expand Up @@ -60,6 +60,27 @@ describe('Translations Base', () => {
.should('be.visible');
});

it.only('shows base and existing exact forms', () => {

Check warning on line 63 in e2e/cypress/e2e/translations/plurals.cy.ts

View workflow job for this annotation

GitHub Actions / E2E Static Check 🪲

it.only not permitted
createKey(
project.id,
'Test key',
{
en: 'You have {testValue, plural, one {# item} =2 {Two items} other {# items}}',
cs: 'Máte {testValue, plural, one {# položku} =4 {# položky } few {# položky} other {# položek}}',
},
{ isPlural: true }
);
visitTranslations(project.id);
waitForGlobalLoading();
getTranslationCell('Test key', 'cs').click();
gcyAdvanced({ value: 'translation-editor', variant: '=2' }).should(
'be.visible'
);
gcyAdvanced({ value: 'translation-editor', variant: '=4' }).should(
'be.visible'
);
});

it('will change plural parameter name for all translations', () => {
createKey(
project.id,
Expand Down
2 changes: 2 additions & 0 deletions webapp/src/views/projects/translations/TranslationEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const TranslationEditor = ({ mode, tools, editorRef }: Props) => {
handleSave,
handleClose,
handleInsertBase,
baseValue,
} = tools;

return (
Expand All @@ -30,6 +31,7 @@ export const TranslationEditor = ({ mode, tools, editorRef }: Props) => {
autofocus={true}
activeEditorRef={editorRef}
mode={mode}
baseValue={baseValue}
editorProps={{
shortcuts: [
{ key: 'Escape', run: () => (handleClose(true), true) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const TranslationWrite: React.FC<Props> = ({ tools }) => {
handleInsertBase,
editEnabled,
disabled,
baseText,
} = tools;
const editVal = tools.editVal!;
const state = translation?.state || 'UNTRANSLATED';
Expand All @@ -68,7 +69,7 @@ export const TranslationWrite: React.FC<Props> = ({ tools }) => {

const baseTranslation = useBaseTranslation(
activeVariant,
keyData.translations[baseLanguage]?.text,
baseText,
keyData.keyIsPlural
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Props = {
autofocus?: boolean;
activeEditorRef?: RefObject<EditorView | null>;
mode: 'placeholders' | 'syntax';
baseValue?: TolgeeFormat;
};

export const PluralEditor = ({
Expand All @@ -29,6 +30,7 @@ export const PluralEditor = ({
activeEditorRef,
editorProps,
mode,
baseValue,
}: Props) => {
function handleChange(text: string, variant: string) {
onChange?.({ ...value, variants: { ...value.variants, [variant]: text } });
Expand All @@ -38,13 +40,25 @@ export const PluralEditor = ({

const editorMode = project.icuPlaceholders ? mode : 'plain';

function getExactForms() {
if (!baseValue) {
return [];
}
return Object.keys(baseValue.variants)
.filter((key) => /^=\d+(\.\d+)?$/.test(key))
.map((key) => parseFloat(key.substring(1)));
}

const exactForms = getExactForms();

return (
<TranslationPlurals
value={value}
locale={locale}
showEmpty
activeVariant={activeVariant}
variantPaddingTop="8px"
exactForms={exactForms}
render={({ content, variant, exampleValue }) => {
const variantOrOther = variant || 'other';
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useMemo } from 'react';
import React, { useMemo } from 'react';
import { styled } from '@mui/material';
import React from 'react';
import {
TolgeeFormat,
getPluralVariants,
getVariantExample,
TolgeeFormat,
} from '@tginternal/editor';

const StyledContainer = styled('div')`
Expand Down Expand Up @@ -67,6 +66,7 @@ type Props = {
showEmpty?: boolean;
activeVariant?: string;
variantPaddingTop?: number | string;
exactForms?: number[];
};

export const TranslationPlurals = ({
Expand All @@ -76,19 +76,12 @@ export const TranslationPlurals = ({
showEmpty,
activeVariant,
variantPaddingTop,
exactForms,
}: Props) => {
const variants = useMemo(() => {
const existing = new Set(Object.keys(value.variants));
const required = getPluralVariants(locale);
required.forEach((val) => existing.delete(val));
const result = Array.from(existing).map((value) => {
return [value, getVariantExample(locale, value)] as const;
});
required.forEach((value) => {
result.push([value, getVariantExample(locale, value)]);
});
return result;
}, [locale]);
const variants = useMemo(
() => getForms(locale, value, exactForms),
[locale, exactForms, value]
);

if (value.parameter) {
return (
Expand Down Expand Up @@ -137,3 +130,27 @@ export const TranslationPlurals = ({
</StyledContainerSimple>
);
};

function getForms(locale: string, value: TolgeeFormat, exactForms?: number[]) {
const forms: Set<string> = new Set();
getPluralVariants(locale).forEach((value) => forms.add(value));
Object.keys(value.variants).forEach((value) => forms.add(value));
(exactForms || [])
.map((value) => `=${value.toString()}`)
.forEach((value) => forms.add(value));

const formsArray = sortExactForms(forms);

return formsArray.map((value) => {
return [value, getVariantExample(locale, value)] as const;
});
}

function sortExactForms(forms: Set<string>) {
return [...forms].sort((a, b) => {
if (a.startsWith('=') && b.startsWith('=')) {
return Number(a.substring(1)) - Number(b.substring(1));
}
return 0;
});
}
30 changes: 25 additions & 5 deletions webapp/src/views/projects/translations/useTranslationCell.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useEffect } from 'react';
import React, { useEffect, useMemo } from 'react';
import { getTolgeeFormat } from '@tginternal/editor';

import { TRANSLATION_STATES } from 'tg.constants/translationStates';
import { useProjectPermissions } from 'tg.hooks/useProjectPermissions';
import { components } from 'tg.service/apiSchema.generated';

import {
useTranslationsSelector,
useTranslationsActions,
useTranslationsSelector,
} from './context/TranslationsContext';
import {
AfterCommand,
Expand Down Expand Up @@ -88,13 +88,23 @@ export const useTranslationCell = ({
});
};

const getBaseText = () => {
if (!baseLanguage) {
return undefined;
}

return keyData.translations[baseLanguage.tag].text;
};

const baseText = getBaseText();

const handleInsertBase = () => {
if (!baseLanguage?.tag) {
const baseText = getBaseText();

if (!baseText) {
return;
}

const baseText = keyData.translations[baseLanguage.tag].text;

let baseVariant: string | undefined;
if (cursor?.activeVariant) {
const variants = getTolgeeFormat(
Expand All @@ -112,6 +122,14 @@ export const useTranslationCell = ({
}
};

const baseValue = useMemo(() => {
return getTolgeeFormat(
getBaseText() || '',
keyData.keyIsPlural,
!project.icuPlaceholders
);
}, [baseText, keyData.keyIsPlural]);

const handleClose = (force = false) => {
if (force) {
setEditForce(undefined);
Expand Down Expand Up @@ -171,5 +189,7 @@ export const useTranslationCell = ({
editEnabled,
translation,
disabled,
baseValue,
baseText,
};
};

0 comments on commit 9c5b996

Please sign in to comment.