Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Handling plural translations #30645

Merged
merged 15 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/grumpy-trainers-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Apply plural translations at a few places.
26 changes: 24 additions & 2 deletions apps/meteor/app/utils/lib/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,31 @@ import { isObject } from '../../../lib/utils/isObject';

export const i18n = i18next.use(sprintf);

export const addSprinfToI18n = function (t: (typeof i18n)['t']) {
type HasCounter = {
counter?: number;
};

const hasCounterProperty = (obj: any): obj is HasCounter => obj?.hasOwnProperty('counter') && typeof obj.counter === 'number';

export const addSprinfToI18n = function (t: (typeof i18n)['t'], i18nInstance?: typeof i18n) {
return function (key: string, ...replaces: any): string {
if (replaces[0] === undefined || isObject(replaces[0])) {
if (replaces[0] === undefined) {
return t(key, ...replaces);
}

if (isObject(replaces[0])) {
if (!hasCounterProperty(replaces[0])) {
return t(key, ...replaces);
}

const pluralKey = `${key}_plural`;
const pluralKeyExists = i18nInstance?.exists(pluralKey);
const counter = replaces[0]?.counter;

if (counter !== undefined && pluralKeyExists) {
return counter === 1 ? t(key, ...replaces) : t(pluralKey, ...replaces);
}

return t(key, ...replaces);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ const ConnectionStatusBar: FC = function ConnectionStatusBar() {
<Icon name='warning' /> {t('meteor_status' as Parameters<typeof t>[0], { context: status })}
</strong>

{status === 'waiting' && <> {t('meteor_status_reconnect_in', { count: reconnectCountdown })}</>}
{status === 'waiting' && (
<>
{' '}
{t(reconnectCountdown === 1 ? 'meteor_status_reconnect_in' : 'meteor_status_reconnect_in_plural', { count: reconnectCountdown })}
</>
)}

{['waiting', 'offline'].includes(status) && (
<>
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/client/providers/TranslationProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ const TranslationProviderInner = ({
loadLanguage: async (language: string): Promise<void> => {
i18n.changeLanguage(language).then(() => applyCustomTranslations());
},
translate: Object.assign(addSprinfToI18n(t), {
translate: Object.assign(addSprinfToI18n(t, i18n), {
has: ((key, options) => key && i18n.exists(key, options)) as TranslationContextValue['translate']['has'],
}),
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ const getBadgeTitle = (
) => {
const title = [] as string[];
if (userMentions) {
title.push(t('mentions_counter', { count: userMentions }));
title.push(t('mentions_counter', { counter: userMentions }));
}
if (threadUnread) {
title.push(t('threads_counter', { count: threadUnread }));
title.push(t('threads_counter', { counter: threadUnread }));
}
if (groupMentions) {
title.push(t('group_mentions_counter', { count: groupMentions }));
title.push(t('group_mentions_counter', { counter: groupMentions }));
}
const count = unread - userMentions - groupMentions;
if (count > 0) {
title.push(t('unread_messages_counter', { count }));
title.push(t('unread_messages_counter', { counter: count }));
}
return title.join(', ');
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const EnabledAppsCount = ({
}): ReactElement | null => {
const t = useTranslation();

const privateAppsCountText: string = t('Private_Apps_Count_Enabled', { count: enabled });
const marketplaceAppsCountText: string = t('Apps_Count_Enabled', { count: enabled });
const privateAppsCountText: string = t('Private_Apps_Count_Enabled', { counter: enabled });
const marketplaceAppsCountText: string = t('Apps_Count_Enabled', { counter: enabled });

return (
<GenericResourceUsage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const PruneMessagesWithData = (): ReactElement => {
throw new Error(t('No_messages_found_to_prune'));
}

dispatchToastMessage({ type: 'success', message: t('__count__message_pruned', { count }) });
dispatchToastMessage({ type: 'success', message: t('__count__message_pruned', { counter: count }) });
methods.reset();
} catch (error: unknown) {
dispatchToastMessage({ type: 'error', message: error });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const VideoConfListItem = ({
</Avatar.Stack>
<Box mis={4}>
{joinedUsers.length > VIDEOCONF_STACK_MAX_USERS
? t('__usersCount__member_joined', { usersCount: joinedUsers.length - VIDEOCONF_STACK_MAX_USERS })
? t('__usersCount__member_joined', { counter: joinedUsers.length - VIDEOCONF_STACK_MAX_USERS })
: t('joined')}
</Box>
</Box>
Expand Down
10 changes: 5 additions & 5 deletions apps/meteor/packages/rocketchat-i18n/i18n/de.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"500": "Interner Serverfehler",
"__count__empty_rooms_will_be_removed_automatically": "{{count}} leere Räume werden automatisch entfernt.",
"__count__empty_rooms_will_be_removed_automatically__rooms__": "{{count}} leere Räume werden automatisch entfernt:<br/> {{rooms}}.",
"__count__message_pruned": "{{count}} Nachricht gelöscht",
"__count__message_pruned_plural": "{{count}} Nachrichten gelöscht",
"__usersCount__member_joined": "+ {{usersCount}} Mitglied(er) beigetreten",
"__usersCount__member_joined_plural": "+ {{usersCount}} Mitglieder beigetreten",
"__count__message_pruned": "{{counter}} Nachricht gelöscht",
"__count__message_pruned_plural": "{{counter}} Nachrichten gelöscht",
"__usersCount__member_joined": "+ {{counter}} Mitglied(er) beigetreten",
"__usersCount__member_joined_plural": "+ {{counter}} Mitglieder beigetreten",
"__usersCount__people_will_be_invited": "{{usersCount}} Mitglieder werden eingeladen",
"__username__is_no_longer__role__defined_by__user_by_": "{{username}} ist nicht länger {{role}}, geändert durch {{user_by}}",
"__username__was_set__role__by__user_by_": "{{username}} ist jetzt {{role}}, geändert durch {{user_by}}",
Expand Down Expand Up @@ -5522,4 +5522,4 @@
"RegisterWorkspace_Connection_Error": "Beim Verbinden ist ein Fehler aufgetreten",
"cloud.RegisterWorkspace_Setup_Terms_Privacy": "Ich bin mit den Nutzungsvereinbarung und den Datenschutzbestimmungen einverstanden",
"Uninstall_grandfathered_app": "{{appName}} deinstallieren?"
}
}
36 changes: 18 additions & 18 deletions apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
"__agents__agents_and__count__conversations__period__": "{{agents}} agents and {{count}} conversations, {{period}}",
"__count__empty_rooms_will_be_removed_automatically": "{{count}} empty rooms will be removed automatically.",
"__count__empty_rooms_will_be_removed_automatically__rooms__": "{{count}} empty rooms will be removed automatically:<br/> {{rooms}}.",
"__count__message_pruned": "{{count}} message pruned",
"__count__message_pruned_plural": "{{count}} messages pruned",
"__count__message_pruned": "{{counter}} message pruned",
"__count__message_pruned_plural": "{{counter}} messages pruned",
"__count__conversations__period__": "{{count}} conversations, {{period}}",
"__count__tags__and__count__conversations__period__": "{{count}} tags and {{conversations}} conversations, {{period}}",
"__departments__departments_and__count__conversations__period__": "{{departments}} departments and {{count}} conversations, {{period}}",
"__usersCount__member_joined": "+ {{usersCount}} member joined",
"__usersCount__member_joined_plural": "+ {{usersCount}} members joined",
"__usersCount__member_joined": "+ {{counter}} member joined",
"__usersCount__member_joined_plural": "+ {{counter}} members joined",
"__usersCount__people_will_be_invited": "{{usersCount}} people will be invited",
"__username__is_no_longer__role__defined_by__user_by_": "{{username}} is no longer {{role}} by {{user_by}}",
"__username__was_set__role__by__user_by_": "{{username}} was set {{role}} by {{user_by}}",
Expand Down Expand Up @@ -532,10 +532,10 @@
"Apps_context_requested": "Requested",
"Apps_context_private": "Private Apps",
"Apps_context_premium": "Premium",
"Apps_Count_Enabled": "{{count}} app enabled",
"Apps_Count_Enabled_plural": "{{count}} apps enabled",
"Private_Apps_Count_Enabled": "{{count}} private app enabled",
"Private_Apps_Count_Enabled_plural": "{{count}} private apps enabled",
"Apps_Count_Enabled": "{{counter}} app enabled",
"Apps_Count_Enabled_plural": "{{counter}} apps enabled",
"Private_Apps_Count_Enabled": "{{counter}} private app enabled",
"Private_Apps_Count_Enabled_plural": "{{counter}} private apps enabled",
"Apps_Count_Enabled_tooltip": "Community Edition workspaces can enable up to {{number}} {{context}} apps",
"Apps_disabled_when_Enterprise_trial_ended": "Apps disabled when Enterprise trial ended",
"Apps_disabled_when_Enterprise_trial_ended_description": "Workspaces on Community Edition can have up to 5 marketplace apps and 3 private apps enabled. Ask your workspace admin to reenable apps.",
Expand Down Expand Up @@ -3515,7 +3515,7 @@
"meteor_status_connecting": "Connecting...",
"meteor_status_failed": "The server connection failed",
"meteor_status_offline": "Offline mode.",
"meteor_status_reconnect_in": "trying again in one second...",
"meteor_status_reconnect_in": "trying again in 1 second...",
"meteor_status_reconnect_in_plural": "trying again in {{count}} seconds...",
"meteor_status_try_now_offline": "Connect again",
"meteor_status_try_now_waiting": "Try now",
Expand Down Expand Up @@ -6086,14 +6086,14 @@
"Filter_by_room": "Filter by room type",
"Filter_by_visibility": "Filter by visibility",
"Theme_Appearence": "Theme Appearence",
"mentions_counter": "{{count}} mention",
"mentions_counter_plural": "{{count}} mentions",
"threads_counter": "{{count}} unread threaded message",
"threads_counter_plural": "{{count}} unread threaded messages",
"group_mentions_counter": "{{count}} group mention",
"group_mentions_counter_plural": "{{count}} group mentions",
"unread_messages_counter": "{{count}} unread message",
"unread_messages_counter_plural": "{{count}} unread messages",
"mentions_counter": "{{counter}} mention",
"mentions_counter_plural": "{{counter}} mentions",
"threads_counter": "{{counter}} unread threaded message",
"threads_counter_plural": "{{counter}} unread threaded messages",
"group_mentions_counter": "{{counter}} group mention",
"group_mentions_counter_plural": "{{counter}} group mentions",
"unread_messages_counter": "{{counter}} unread message",
"unread_messages_counter_plural": "{{counter}} unread messages",
"Premium": "Premium",
"Premium_capability": "Premium capability"
}
}
18 changes: 9 additions & 9 deletions apps/meteor/packages/rocketchat-i18n/i18n/fi.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"500": "Sisäinen palvelinvirhe",
"__count__empty_rooms_will_be_removed_automatically": "{{count}} tyhjää huonetta poistetaan automaattisesti.",
"__count__empty_rooms_will_be_removed_automatically__rooms__": "{{count}} tyhjää huonetta poistetaan automaattisesti:<br/> {{rooms}}.",
"__count__message_pruned": "{{count}} viesti karsittu",
"__count__message_pruned_plural": "{{count}} viestiä karsittu",
"__usersCount__member_joined": "+ {{usersCount}} jäsen liittyi",
"__usersCount__member_joined_plural": "+ {{usersCount}} jäsentä liittynyt",
"__count__message_pruned": "{{counter}} viesti karsittu",
"__count__message_pruned_plural": "{{counter}} viestiä karsittu",
"__usersCount__member_joined": "+ {{counter}} jäsen liittyi",
"__usersCount__member_joined_plural": "+ {{counter}} jäsentä liittynyt",
"__usersCount__people_will_be_invited": "{{usersCount}} henkilöä kutsutaan",
"__username__is_no_longer__role__defined_by__user_by_": "{{username}} ei ole enää {{role}} (muutoksen teki {{user_by}})",
"__username__was_set__role__by__user_by_": "{{user_by}} muutti käyttäjän {{username}} rooliksi {{role}} ",
Expand Down Expand Up @@ -502,10 +502,10 @@
"Apps_context_installed": "Asennettu",
"Apps_context_requested": "Pyydetty",
"Apps_context_private": "Yksityiset sovellukset",
"Apps_Count_Enabled": "{{count}} sovellus käytössä",
"Apps_Count_Enabled_plural": "{{count}} sovellusta käytössä",
"Private_Apps_Count_Enabled": "{{count}} yksityistä sovellusta käytössä",
"Private_Apps_Count_Enabled_plural": "{{count}} yksityistä sovellusta käytössä",
"Apps_Count_Enabled": "{{counter}} sovellus käytössä",
"Apps_Count_Enabled_plural": "{{counter}} sovellusta käytössä",
"Private_Apps_Count_Enabled": "{{counter}} yksityistä sovellusta käytössä",
"Private_Apps_Count_Enabled_plural": "{{counter}} yksityistä sovellusta käytössä",
"Apps_Count_Enabled_tooltip": "Yhteisöversion työtiloissa voi ottaa käyttöön enintään {{number}} {{context}}sovellusta",
"Apps_disabled_when_Enterprise_trial_ended": "Sovellukset poistuivat käytöstä, kun yritysversion kokeilujakso päättyi",
"Apps_disabled_when_Enterprise_trial_ended_description": "Yhteisöversion työtiloissa voi olla käytössä enintään 5 markkinapaikkasovellusta ja 3 yksityistä sovellusta. Pyydä työtilan järjestelmänvalvojaa ottamaan sovelluksia käyttöön uudelleen.",
Expand Down Expand Up @@ -5749,4 +5749,4 @@
"Uninstall_grandfathered_app": "Poistetaanko {{appName}}?",
"App_will_lose_grandfathered_status": "**Tämä {{context}}sovellus menettää aikaisemmin käytetössä olleen sovelluksen tilansa.** \n \nYhteisöversion työtiloissa voi olla käytössä enintään {{limit}} {{context}} sovellusta. aikaisemmin Aikaisemmin käytössä olleet sovellukset lasketaan mukaan rajoitukseen, mutta rajoitusta ei sovelleta niihin.",
"Theme_Appearence": "Teeman ulkoasu"
}
}
6 changes: 3 additions & 3 deletions apps/meteor/packages/rocketchat-i18n/i18n/hu.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"500": "Belső kiszolgálóhiba",
"__count__empty_rooms_will_be_removed_automatically": "{{count}} üres szoba automatikusan eltávolításra kerül.",
"__count__empty_rooms_will_be_removed_automatically__rooms__": "{{count}} üres szoba automatikusan eltávolításra kerül:<br/> {{rooms}}.",
"__count__message_pruned": "{{count}} üzenet törölve",
"__count__message_pruned_plural": "{{count}} üzenet törölve",
"__count__message_pruned": "{{counter}} üzenet törölve",
"__count__message_pruned_plural": "{{counter}} üzenet törölve",
"__usersCount__member_joined": "+{{usersCount}} tag csatlakozott",
"__usersCount__member_joined_plural": "+{{usersCount}} tag csatlakozott",
"__usersCount__people_will_be_invited": "{{usersCount}} személy lesz meghívva",
Expand Down Expand Up @@ -5430,4 +5430,4 @@
"Join_your_team": "Csatlakozás csapathoz",
"Create_an_account": "Fiók létrehozása",
"RegisterWorkspace_Features_Marketplace_Title": "Piactér"
}
}
8 changes: 4 additions & 4 deletions apps/meteor/packages/rocketchat-i18n/i18n/it.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"500": "Errore interno del server",
"__count__empty_rooms_will_be_removed_automatically": "{{count}} stanze vuote verranno automaticamente rimosse.",
"__count__empty_rooms_will_be_removed_automatically__rooms__": "{{count}} stanze vuote saranno rimosse automaticamente:<br/> {{rooms}}.",
"__count__message_pruned": "{{count}} messaggio eliminato",
"__count__message_pruned_plural": "{{count}} messaggi eliminati",
"__usersCount__member_joined_plural": "+ {{usersCount}} membri si sono uniti",
"__count__message_pruned": "{{counter}} messaggio eliminato",
"__count__message_pruned_plural": "{{counter}} messaggi eliminati",
"__usersCount__member_joined_plural": "+ {{counter}} membri si sono uniti",
"__usersCount__people_will_be_invited": "{{usersCount}} persone saranno invitate",
"__username__is_no_longer__role__defined_by__user_by_": "{{username}} non è più {{role}}, da {{user_by}}",
"__username__was_set__role__by__user_by_": "A {{username}} è stato assegnato il ruolo di {{role}} da {{user_by}}",
Expand Down Expand Up @@ -2861,4 +2861,4 @@
"registration.component.form.invalidConfirmPass": "La password di conferma non corrisponde con la password",
"registration.component.form.confirmPassword": "Conferma la tua password",
"registration.component.form.sendConfirmationEmail": "Invia email di conferma"
}
}
10 changes: 5 additions & 5 deletions apps/meteor/packages/rocketchat-i18n/i18n/pl.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"500": "Wewnętrzny błąd serwera",
"__count__empty_rooms_will_be_removed_automatically": "Liczba pokojów do automatycznego usunięcia: {{count}}.",
"__count__empty_rooms_will_be_removed_automatically__rooms__": "Puste pokoje ({{count}}) zostaną automatycznie usunięte:<br/> {{rooms}}.",
"__count__message_pruned": "{{count}} wiadomość(i) usuniętych",
"__count__message_pruned_plural": "{{count}} wiadomość(i) usuniętych",
"__usersCount__member_joined": "+ {{usersCount}} członek dołączył",
"__usersCount__member_joined_plural": "+ {{usersCount}} członków dołączyło",
"__count__message_pruned": "{{counter}} wiadomość(i) usuniętych",
"__count__message_pruned_plural": "{{counter}} wiadomość(i) usuniętych",
"__usersCount__member_joined": "+ {{counter}} członek dołączył",
"__usersCount__member_joined_plural": "+ {{counter}} członków dołączyło",
"__usersCount__people_will_be_invited": "{{usersCount}} ludzi zostanie zostanie zaproszonych",
"__username__is_no_longer__role__defined_by__user_by_": "Użytkownik {{username}} nie ma już roli {{role}}; zmienił to użytkownik {{user_by}}",
"__username__was_set__role__by__user_by_": "Użytkownik {{username}} otrzymał rolę {{role}} od użytkownika {{user_by}}",
Expand Down Expand Up @@ -5350,4 +5350,4 @@
"RegisterWorkspace_Setup_Label": "E-mail konta w chmurze",
"RegisterWorkspace_Syncing_Complete": "Synchronizacja zakończona",
"cloud.RegisterWorkspace_Setup_Terms_Privacy": "Zgadzam się z <1>zasadami i warunkami</1> i <3>Polityką prywatności</3>."
}
}
8 changes: 4 additions & 4 deletions apps/meteor/packages/rocketchat-i18n/i18n/pt-BR.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
"__agents__agents_and__count__conversations__period__": "{{agents}} agentes e {{count}} conversas, {{period}}",
"__count__empty_rooms_will_be_removed_automatically": "{{count}} salas vazias serão removidas automaticamente.",
"__count__empty_rooms_will_be_removed_automatically__rooms__": "{{count}} salas vazias serão removidas automaticamente:<br/> {{rooms}}.",
"__count__message_pruned": "{{count}} mensagem apagada",
"__count__message_pruned_plural": "{{count}} mensagens apagadas",
"__count__message_pruned": "{{counter}} mensagem apagada",
"__count__message_pruned_plural": "{{counter}} mensagens apagadas",
"__count__conversations__period__": "{{count}} conversas, {{period}}",
"__count__tags__and__count__conversations__period__": "{{count}} tags e {{conversations}} conversas, {{period}}",
"__departments__departments_and__count__conversations__period__": "{{departments}} departmentos e {{count}} conversas, {{period}}",
"__usersCount__member_joined_plural": "+ {{usersCount}} membros entraram",
"__usersCount__member_joined_plural": "+ {{counter}} membros entraram",
"__usersCount__people_will_be_invited": "{{usersCount}} usuários vão ser convidados",
"__username__is_no_longer__role__defined_by__user_by_": "{{username}} não pertence mais a {{role}}, por {{user_by}}",
"__username__was_set__role__by__user_by_": "{{username}} foi definido como {{role}} por {{user_by}}",
Expand Down Expand Up @@ -4970,4 +4970,4 @@
"RegisterWorkspace_Features_Omnichannel_Title": "Omnichannel",
"RegisterWorkspace_Setup_Label": "E-mail da conta da nuvem",
"cloud.RegisterWorkspace_Setup_Terms_Privacy": "Eu concordo com os <1>Termos e condições</1> e a <3>Política de privacidade</3>"
}
}
Loading
Loading