Skip to content

Commit a725fd4

Browse files
authored
feat: [a11y and i18n] Translate time phrases (#1232)
1 parent 2907418 commit a725fd4

File tree

9 files changed

+73
-9
lines changed

9 files changed

+73
-9
lines changed

src/js/lang/en.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ export const En = {
6666
'An unsupported error occurred. The server or network failed, or your browser does not support this format.',
6767
'The media is encrypted and there are no keys to decrypt it.':
6868
'The media is encrypted and there are no keys to decrypt it.',
69+
hour: 'hour',
70+
hours: 'hours',
71+
minute: 'minute',
72+
minutes: 'minutes',
73+
second: 'second',
74+
seconds: 'seconds',
75+
'{time} remaining': '{time} remaining',
76+
'{currentTime} of {totalTime}': '{currentTime} of {totalTime}',
77+
'video not loaded, unknown time.': 'video not loaded, unknown time.',
6978
} as const;
7079

7180
export type TranslateKeys = keyof typeof En;

src/js/lang/es.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ export const Es: TranslateDictionary = {
6868
'Ocurrió un error de incompatibilidad. El servidor o la red fallaron, o tu navegador no admite este formato.',
6969
'The media is encrypted and there are no keys to decrypt it.':
7070
'El contenido está cifrado y no hay claves disponibles para descifrarlo.',
71+
hour: 'hora',
72+
hours: 'horas',
73+
minute: 'minuto',
74+
minutes: 'minutos',
75+
second: 'segundo',
76+
seconds: 'segundos',
77+
'{time} remaining': '{time} restante',
78+
'{currentTime} of {totalTime}': '{currentTime} de {totalTime}',
79+
'video not loaded, unknown time.': 'video no cargado, tiempo desconocido.',
7180
};
7281

7382
addTranslation('es', Es);

src/js/lang/fr.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ export const Fr: TranslateDictionary = {
6868
'Une erreur non supportée s’est produite. Le serveur ou le réseau a échoué, ou votre navigateur ne prend pas en charge ce format.',
6969
'The media is encrypted and there are no keys to decrypt it.':
7070
'Le média est chiffré et il n’y a pas de clés pour le déchiffrer.',
71+
hour: 'heure',
72+
hours: 'heures',
73+
minute: 'minute',
74+
minutes: 'minutes',
75+
second: 'seconde',
76+
seconds: 'secondes',
77+
'{time} remaining': '{time} restant',
78+
'{currentTime} of {totalTime}': '{currentTime} sur {totalTime}',
79+
'video not loaded, unknown time.': 'vidéo non chargée, durée inconnue.',
7180
};
7281

7382
addTranslation('fr', Fr);

src/js/lang/pt.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,14 @@ export const Pt: TranslateDictionary = {
6868
'Ocorreu um erro de incompatibilidade. O servidor ou a rede falharam, ou seu navegador não suporta este formato.',
6969
'The media is encrypted and there are no keys to decrypt it.':
7070
'O conteúdo está criptografado e não há chaves disponíveis para descriptografá-lo.',
71+
hour: 'hora',
72+
hours: 'horas',
73+
minute: 'minuto',
74+
minutes: 'minutos',
75+
second: 'segundo',
76+
seconds: 'segundos',
77+
'{time} remaining': '{time} restante',
78+
'{currentTime} of {totalTime}': '{currentTime} de {totalTime}',
79+
'video not loaded, unknown time.': 'vídeo não carregado, tempo desconhecido.',
7180
};
7281
addTranslation('pt', Pt);

src/js/lang/zh-CN.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,14 @@ export const ZhCn: TranslateDictionary = {
6868
'发生未支持的错误,可能是服务器或网络故障,或浏览器不支持该格式。',
6969
'The media is encrypted and there are no keys to decrypt it.':
7070
'媒体已加密,缺少解密密钥。',
71+
hour: '小时',
72+
hours: '小时',
73+
minute: '分钟',
74+
minutes: '分钟',
75+
second: '秒',
76+
seconds: '秒',
77+
'{time} remaining': '剩余 {time}',
78+
'{currentTime} of {totalTime}': '{currentTime} / {totalTime}',
79+
'video not loaded, unknown time.': '视频未加载,时间未知。',
7180
};
7281
addTranslation('zh-CN', ZhCn);

src/js/lang/zh-TW.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ export const ZhTw: TranslateDictionary = {
6868
'發生不支援的錯誤。伺服器或網路可能有問題,或瀏覽器不支援這個格式。',
6969
'The media is encrypted and there are no keys to decrypt it.':
7070
'媒體已加密,但找不到解密金鑰。',
71+
hour: '小時',
72+
hours: '小時',
73+
minute: '分鐘',
74+
minutes: '分鐘',
75+
second: '秒',
76+
seconds: '秒',
77+
'{time} remaining': '剩餘 {time}',
78+
'{currentTime} of {totalTime}': '{currentTime} / {totalTime}',
79+
'video not loaded, unknown time.': '影片未載入,時間未知。',
7180
};
7281

7382
addTranslation('zh-TW', ZhTw);

src/js/media-time-display.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const updateAriaValueText = (el: MediaTimeDisplay): void => {
6363
endTime = seekableEnd;
6464
}
6565
if (currentTime == null || endTime === null) {
66-
el.setAttribute('aria-valuetext', DEFAULT_MISSING_TIME_PHRASE);
66+
el.setAttribute('aria-valuetext', t(DEFAULT_MISSING_TIME_PHRASE));
6767
return;
6868
}
6969

@@ -76,7 +76,10 @@ const updateAriaValueText = (el: MediaTimeDisplay): void => {
7676
return;
7777
}
7878
const totalTimePhrase = formatAsTimePhrase(endTime);
79-
const fullPhrase = `${currentTimePhrase} of ${totalTimePhrase}`;
79+
const fullPhrase = t('{currentTime} of {totalTime}', {
80+
currentTime: currentTimePhrase,
81+
totalTime: totalTimePhrase,
82+
});
8083
el.setAttribute('aria-valuetext', fullPhrase);
8184
};
8285

src/js/media-time-range.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ const updateAriaValueText = (el: any): void => {
3535
const currentTimePhrase = formatAsTimePhrase(+calcTimeFromRangeValue(el));
3636
const totalTimePhrase = formatAsTimePhrase(+el.mediaSeekableEnd);
3737
const fullPhrase = !(currentTimePhrase && totalTimePhrase)
38-
? DEFAULT_MISSING_TIME_PHRASE
39-
: `${currentTimePhrase} of ${totalTimePhrase}`;
38+
? t(DEFAULT_MISSING_TIME_PHRASE)
39+
: t('{currentTime} of {totalTime}', {
40+
currentTime: currentTimePhrase,
41+
totalTime: totalTimePhrase,
42+
});
4043
range.setAttribute('aria-valuetext', fullPhrase);
4144
};
4245

src/js/utils/time.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { isValidNumber } from './utils.js';
2+
import { t } from './i18n.js';
23

34
const UnitLabels = [
45
{
@@ -13,12 +14,13 @@ const UnitLabels = [
1314
singular: 'second',
1415
plural: 'seconds',
1516
},
16-
];
17+
] as const;
18+
1719
const toTimeUnitPhrase = (timeUnitValue, unitIndex) => {
1820
const unitLabel =
1921
timeUnitValue === 1
20-
? UnitLabels[unitIndex].singular
21-
: UnitLabels[unitIndex].plural;
22+
? t(UnitLabels[unitIndex].singular)
23+
: t(UnitLabels[unitIndex].plural);
2224

2325
return `${timeUnitValue} ${unitLabel}`;
2426
};
@@ -52,9 +54,11 @@ export const formatAsTimePhrase = (seconds) => {
5254
.join(', ');
5355

5456
// If the time was negative, assume it represents some remaining amount of time/"count down".
55-
const negativeSuffix = negative ? ' remaining' : '';
57+
if (negative) {
58+
return t('{time} remaining', { time: timeString });
59+
}
5660

57-
return `${timeString}${negativeSuffix}`;
61+
return timeString;
5862
};
5963

6064
/**

0 commit comments

Comments
 (0)