Skip to content

Commit 0965ca1

Browse files
shakyShaneShane Osbourne
andauthored
ntp: prepare translations (#1262)
* ntp: modular translations * lint * ntp: stats tweaks * re-introduce the subtitle * fixed rebase * fixed I * more tweaks * more tweaks * more tweaks * better notes * better notes --------- Co-authored-by: Shane Osbourne <[email protected]>
1 parent 652a7cc commit 0965ca1

File tree

25 files changed

+338
-208
lines changed

25 files changed

+338
-208
lines changed

special-pages/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"main": "index.js",
77
"type": "module",
88
"scripts": {
9-
"prebuild": "node types.mjs",
9+
"prebuild": "node types.mjs && node translations.mjs",
1010
"build": "node index.mjs",
1111
"build.dev": "npm run build -- --env development",
1212
"test-unit": "node --test unit-test/translations.mjs pages/duckplayer/unit-tests/embed-settings.mjs",
@@ -20,7 +20,7 @@
2020
"test.headed": "npm run test-int -- --headed",
2121
"test.ui": "npm run test-int -- --ui",
2222
"serve": "http-server -c-1 --port 3210 ../build/integration/pages",
23-
"watch": "chokidar pages shared --initial -c 'npm run build.dev'"
23+
"watch": "chokidar pages shared --initial -c 'npm run build.dev' --ignore 'pages/**/locales'"
2424
},
2525
"license": "ISC",
2626
"devDependencies": {

special-pages/pages/new-tab/app/favorites/components/Favorites.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import cn from 'classnames';
66
import styles from './Favorites.module.css';
77
import { Placeholder, PlusIconMemo, TileMemo } from './Tile.js';
88
import { ShowHideButton } from '../../components/ShowHideButton.jsx';
9-
import { useTypedTranslation } from '../../types.js';
9+
import { useTypedTranslationWith } from '../../types.js';
1010
import { usePlatformName } from '../../settings.provider.js';
1111
import { useDropzoneSafeArea } from '../../dropzone.js';
1212

@@ -31,7 +31,7 @@ export const FavoritesMemo = memo(Favorites);
3131
*/
3232
export function Favorites({ gridRef, favorites, expansion, toggle, openContextMenu, openFavorite, add }) {
3333
const platformName = usePlatformName();
34-
const { t } = useTypedTranslation();
34+
const { t } = useTypedTranslationWith(/** @type {import('../strings.json')} */ ({}));
3535
const safeArea = useDropzoneSafeArea();
3636

3737
const ROW_CAPACITY = 6;

special-pages/pages/new-tab/app/favorites/components/FavoritesCustomized.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { h } from 'preact';
22
import { useContext } from 'preact/hooks';
33

4-
import { useTelemetry, useTypedTranslation } from '../../types.js';
4+
import { useTelemetry, useTypedTranslationWith } from '../../types.js';
55
import { useVisibility } from '../../widget-list/widget-config.provider.js';
66
import { useCustomizer } from '../../customizer/components/Customizer.js';
77

@@ -38,7 +38,7 @@ export function FavoritesConsumer() {
3838
* Render the favorites widget, with integration into the page customizer
3939
*/
4040
export function FavoritesCustomized() {
41-
const { t } = useTypedTranslation();
41+
const { t } = useTypedTranslationWith(/** @type {import("../strings.json")} */ ({}));
4242
const { id, visibility, toggle, index } = useVisibility();
4343

4444
// register with the visibility menu
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"favorites_show_less": {
3+
"title": "Show less",
4+
"note": "Button label to display fewer items"
5+
},
6+
"favorites_show_more": {
7+
"title": "Show more ({count} remaining)",
8+
"note": "Button text to show hidden items. {count} will be replaced with the number of remaining favorite items to show, including the parentheses. Example: 'Show more (18 remaining)'"
9+
},
10+
"favorites_menu_title": {
11+
"title": "Favorites",
12+
"note": "Used as a label in a customization menu"
13+
}
14+
}

special-pages/pages/new-tab/app/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { SettingsProvider } from './settings.provider.js';
77
import { InitialSetupContext, MessagingContext, TelemetryContext } from './types';
88
import { TranslationProvider } from '../../../shared/components/TranslationsProvider.js';
99
import { WidgetConfigService } from './widget-list/widget-config.service.js';
10-
import enStrings from '../src/locales/en/newtab.json';
10+
import enStrings from '../src/locales/en/new-tab.json';
1111
import { WidgetConfigProvider } from './widget-list/widget-config.provider.js';
1212
import { Settings } from './settings.js';
1313
import { Components } from './components/Components.jsx';

special-pages/pages/new-tab/src/js/mock-transport.js renamed to special-pages/pages/new-tab/app/mock-transport.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
import { TestTransportConfig } from '@duckduckgo/messaging';
22

3-
import { stats } from '../../app/privacy-stats/mocks/stats.js';
4-
import { rmfDataExamples } from '../../app/remote-messaging-framework/mocks/rmf.data.js';
5-
import { favorites, gen } from '../../app/favorites/mocks/favorites.data.js';
6-
import { updateNotificationExamples } from '../../app/update-notification/mocks/update-notification.data.js';
7-
import { variants as nextSteps } from '../../app/next-steps/nextsteps.data.js';
3+
import { stats } from './privacy-stats/mocks/stats.js';
4+
import { rmfDataExamples } from './remote-messaging-framework/mocks/rmf.data.js';
5+
import { favorites, gen } from './favorites/mocks/favorites.data.js';
6+
import { updateNotificationExamples } from './update-notification/mocks/update-notification.data.js';
7+
import { variants as nextSteps } from './next-steps/nextsteps.data.js';
88

99
/**
10-
* @typedef {import('../../../../types/new-tab').Favorite} Favorite
11-
* @typedef {import('../../../../types/new-tab').FavoritesData} FavoritesData
12-
* @typedef {import('../../../../types/new-tab').FavoritesConfig} FavoritesConfig
13-
* @typedef {import('../../../../types/new-tab').StatsConfig} StatsConfig
14-
* @typedef {import('../../../../types/new-tab').NextStepsConfig} NextStepsConfig
15-
* @typedef {import('../../../../types/new-tab').NextStepsCards} NextStepsCards
16-
* @typedef {import('../../../../types/new-tab').NextStepsData} NextStepsData
17-
* @typedef {import('../../../../types/new-tab').UpdateNotificationData} UpdateNotificationData
18-
* @typedef {import('../../../../types/new-tab.js').NewTabMessages['subscriptions']['subscriptionEvent']} SubscriptionNames
10+
* @typedef {import('../../../types/new-tab').Favorite} Favorite
11+
* @typedef {import('../../../types/new-tab').FavoritesData} FavoritesData
12+
* @typedef {import('../../../types/new-tab').FavoritesConfig} FavoritesConfig
13+
* @typedef {import('../../../types/new-tab').StatsConfig} StatsConfig
14+
* @typedef {import('../../../types/new-tab').NextStepsConfig} NextStepsConfig
15+
* @typedef {import('../../../types/new-tab').NextStepsCards} NextStepsCards
16+
* @typedef {import('../../../types/new-tab').NextStepsData} NextStepsData
17+
* @typedef {import('../../../types/new-tab').UpdateNotificationData} UpdateNotificationData
18+
* @typedef {import('../../../types/new-tab').NewTabMessages['subscriptions']['subscriptionEvent']} SubscriptionNames
1919
*/
2020

21-
const VERSION_PREFIX = '__ntp_28__.';
21+
const VERSION_PREFIX = '__ntp_29__.';
2222
const url = new URL(window.location.href);
2323

2424
export function mockTransport() {
@@ -75,7 +75,7 @@ export function mockTransport() {
7575

7676
function clearRmf() {
7777
const listeners = rmfSubscriptions.get('rmf_onDataUpdate') || [];
78-
/** @type {import('../../../../types/new-tab.js').RMFData} */
78+
/** @type {import('../../../types/new-tab.ts').RMFData} */
7979
const message = { content: undefined };
8080
for (const listener of listeners) {
8181
listener(message);
@@ -85,7 +85,7 @@ export function mockTransport() {
8585
return new TestTransportConfig({
8686
notify(_msg) {
8787
window.__playwright_01?.mocks?.outgoing?.push?.({ payload: structuredClone(_msg) });
88-
/** @type {import('../../../../types/new-tab.js').NewTabMessages['notifications']} */
88+
/** @type {import('../../../types/new-tab.ts').NewTabMessages['notifications']} */
8989
const msg = /** @type {any} */ (_msg);
9090
switch (msg.method) {
9191
case 'widgets_setConfig': {
@@ -154,7 +154,7 @@ export function mockTransport() {
154154
},
155155
subscribe(_msg, cb) {
156156
window.__playwright_01?.mocks?.outgoing?.push?.({ payload: structuredClone(_msg) });
157-
/** @type {import('../../../../types/new-tab.js').NewTabMessages['subscriptions']['subscriptionEvent']} */
157+
/** @type {import('../../../types/new-tab.ts').NewTabMessages['subscriptions']['subscriptionEvent']} */
158158
const sub = /** @type {any} */ (_msg.subscriptionName);
159159
switch (sub) {
160160
case 'widgets_onConfigUpdated': {
@@ -303,7 +303,7 @@ export function mockTransport() {
303303
// eslint-ignore-next-line require-await
304304
request(_msg) {
305305
window.__playwright_01?.mocks?.outgoing?.push?.({ payload: structuredClone(_msg) });
306-
/** @type {import('../../../../types/new-tab.js').NewTabMessages['requests']} */
306+
/** @type {import('../../../types/new-tab.ts').NewTabMessages['requests']} */
307307
const msg = /** @type {any} */ (_msg);
308308
switch (msg.method) {
309309
case 'stats_getData': {
@@ -353,7 +353,7 @@ export function mockTransport() {
353353
return Promise.resolve(data);
354354
}
355355
case 'rmf_getData': {
356-
/** @type {import('../../../../types/new-tab.js').RMFData} */
356+
/** @type {import('../../../types/new-tab.ts').RMFData} */
357357
let message = { content: undefined };
358358
const rmfParam = url.searchParams.get('rmf');
359359

@@ -414,7 +414,7 @@ export function mockTransport() {
414414
updateNotification = updateNotificationExamples.populated;
415415
}
416416

417-
/** @type {import('../../../../types/new-tab.js').InitialSetupResponse} */
417+
/** @type {import('../../../types/new-tab.ts').InitialSetupResponse} */
418418
const initial = {
419419
widgets: widgetsFromStorage,
420420
widgetConfigs: widgetConfigFromStorage,

special-pages/pages/new-tab/app/next-steps/components/NextStepsCard.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { h } from 'preact';
22
import styles from './NextSteps.module.css';
33
import { DismissButton } from '../../components/DismissButton';
44
import { variants } from '../nextsteps.data';
5-
import { useTypedTranslation } from '../../types';
5+
import { useTypedTranslationWith } from '../../types';
66

77
/**
88
* @param {object} props
@@ -12,7 +12,7 @@ import { useTypedTranslation } from '../../types';
1212
*/
1313

1414
export function NextStepsCard({ type, dismiss, action }) {
15-
const { t } = useTypedTranslation();
15+
const { t } = useTypedTranslationWith(/** @type {import("../strings.json")} */ ({}));
1616
const message = variants[type]?.(t);
1717
return (
1818
<div class={styles.card}>

special-pages/pages/new-tab/app/next-steps/components/NextStepsGroup.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { h } from 'preact';
22
import cn from 'classnames';
33
import styles from './NextSteps.module.css';
4-
import { useTypedTranslation } from '../../types';
4+
import { useTypedTranslationWith } from '../../types';
55
import { NextStepsCard } from './NextStepsCard';
66
import { otherText } from '../nextsteps.data';
77
import { ShowHideButton } from '../../components/ShowHideButton';
88
import { useId } from 'preact/hooks';
99

1010
/**
11+
* @import enStrings from '../strings.json';
12+
* @import ntpStrings from '../../strings.json';
13+
* @typedef {enStrings & ntpStrings} strings
1114
* @typedef {import('../../../../../types/new-tab').Expansion} Expansion
1215
* @typedef {import('../../../../../types/new-tab').Animation} Animation
1316
* @typedef {import('../../../../../types/new-tab').NextStepsCards} NextStepsCards
@@ -22,7 +25,7 @@ import { useId } from 'preact/hooks';
2225
* @param {(id: string)=>void} props.dismiss
2326
*/
2427
export function NextStepsCardGroup({ types, expansion, toggle, action, dismiss }) {
25-
const { t } = useTypedTranslation();
28+
const { t } = useTypedTranslationWith(/** @type {strings} */ ({}));
2629
const WIDGET_ID = useId();
2730
const TOGGLE_ID = useId();
2831
const alwaysShown = types.length > 2 ? types.slice(0, 2) : types;
@@ -63,7 +66,7 @@ export function NextStepsCardGroup({ types, expansion, toggle, action, dismiss }
6366
}
6467

6568
export function NextStepsBubbleHeader() {
66-
const { t } = useTypedTranslation();
69+
const { t } = useTypedTranslationWith(/** @type {strings} */ ({}));
6770
const text = otherText.nextSteps_sectionTitle(t);
6871
return (
6972
<div class={styles.bubble}>

special-pages/pages/new-tab/app/next-steps/integrations-tests/next-steps.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ test.describe('newtab NextSteps cards', () => {
5252
await expect(page.getByRole('button', { name: 'Try DuckPlayer' })).not.toBeVisible();
5353

5454
// expand the section
55-
await page.getByLabel('Show more', { exact: true }).click();
55+
await page.getByLabel('Show More', { exact: true }).click();
5656

5757
await expect(page.locator('p').filter({ hasText: 'Block Cookie Pop-ups' })).toBeVisible();
5858
await page.getByRole('button', { name: 'Try DuckPlayer' }).click();
Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,57 @@
1+
/**
2+
* @import enStrings from "./strings.json"
3+
* @import ntpStrings from "../strings.json"
4+
*/
15
export const variants = {
2-
/** @param {(translationId: string) => string} t */
6+
/** @param {(translationId: keyof enStrings) => string} t */
37
bringStuff: (t) => ({
48
id: 'bringStuff',
59
icon: 'Bring-Stuff',
610
title: t('nextSteps_bringStuff_title'),
711
summary: t('nextSteps_bringStuff_summary'),
812
actionText: t('nextSteps_bringStuff_actionText'),
913
}),
10-
/** @param {(translationId: string) => string} t */
14+
/** @param {(translationId: keyof enStrings) => string} t */
1115
defaultApp: (t) => ({
1216
id: 'defaultApp',
1317
icon: 'Default-App',
1418
title: t('nextSteps_defaultApp_title'),
1519
summary: t('nextSteps_defaultApp_summary'),
1620
actionText: t('nextSteps_defaultApp_actionText'),
1721
}),
18-
/** @param {(translationId: string) => string} t */
22+
/** @param {(translationId: keyof enStrings) => string} t */
1923
blockCookies: (t) => ({
2024
id: 'blockCookies',
2125
icon: 'Cookie-Pops',
2226
title: t('nextSteps_blockCookies_title'),
2327
summary: t('nextSteps_blockCookies_summary'),
2428
actionText: t('nextSteps_blockCookies_actionText'),
2529
}),
26-
/** @param {(translationId: string) => string} t */
30+
/** @param {(translationId: keyof enStrings) => string} t */
2731
emailProtection: (t) => ({
2832
id: 'emailProtection',
2933
icon: 'Email-Protection',
3034
title: t('nextSteps_emailProtection_title'),
3135
summary: t('nextSteps_emailProtection_summary'),
3236
actionText: t('nextSteps_emailProtection_actionText'),
3337
}),
34-
/** @param {(translationId: string) => string} t */
38+
/** @param {(translationId: keyof enStrings) => string} t */
3539
duckplayer: (t) => ({
3640
id: 'duckplayer',
3741
icon: 'Tube-Clean',
3842
title: t('nextSteps_duckPlayer_title'),
3943
summary: t('nextSteps_duckPlayer_summary'),
4044
actionText: t('nextSteps_duckPlayer_actionText'),
4145
}),
42-
/** @param {(translationId: string) => string} t */
46+
/** @param {(translationId: keyof enStrings) => string} t */
4347
addAppToDockMac: (t) => ({
4448
id: 'addAppToDockMac',
4549
icon: 'Dock-Add-Mac',
4650
title: t('nextSteps_addAppDockMac_title'),
4751
summary: t('nextSteps_addAppDockMac_summary'),
4852
actionText: t('nextSteps_addAppDockMac_actionText'),
4953
}),
50-
/** @param {(translationId: string) => string} t */
54+
/** @param {(translationId: keyof enStrings) => string} t */
5155
pinAppToTaskbarWindows: (t) => ({
5256
id: 'pinAppToTaskbarWindows',
5357
icon: 'Dock-Add-Windows',
@@ -58,10 +62,10 @@ export const variants = {
5862
};
5963

6064
export const otherText = {
61-
/** @param {(translationId: string) => string} t */
65+
/** @param {(translationId: keyof ntpStrings) => string} t */
6266
showMore: (t) => t('ntp_show_more'),
63-
/** @param {(translationId: string) => string} t */
67+
/** @param {(translationId: keyof ntpStrings) => string} t */
6468
showLess: (t) => t('ntp_show_less'),
65-
/** @param {(translationId: string) => string} t */
69+
/** @param {(translationId: keyof enStrings) => string} t */
6670
nextSteps_sectionTitle: (t) => t('nextSteps_sectionTitle'),
6771
};

0 commit comments

Comments
 (0)