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

ntp: prepare translations #1262

Merged
merged 12 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions special-pages/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"main": "index.js",
"type": "module",
"scripts": {
"prebuild": "node types.mjs",
"prebuild": "node types.mjs && node translations.mjs",
"build": "node index.mjs",
"build.dev": "npm run build -- --env development",
"test-unit": "node --test unit-test/translations.mjs pages/duckplayer/unit-tests/embed-settings.mjs",
Expand All @@ -20,7 +20,7 @@
"test.headed": "npm run test-int -- --headed",
"test.ui": "npm run test-int -- --ui",
"serve": "http-server -c-1 --port 3210 ../build/integration/pages",
"watch": "chokidar pages shared --initial -c 'npm run build.dev'"
"watch": "chokidar pages shared --initial -c 'npm run build.dev' --ignore 'pages/**/locales'"
},
"license": "ISC",
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cn from 'classnames';
import styles from './Favorites.module.css';
import { Placeholder, PlusIconMemo, TileMemo } from './Tile.js';
import { ShowHideButton } from '../../components/ShowHideButton.jsx';
import { useTypedTranslation } from '../../types.js';
import { useTypedTranslationWith } from '../../types.js';
import { usePlatformName } from '../../settings.provider.js';
import { useDropzoneSafeArea } from '../../dropzone.js';

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

const ROW_CAPACITY = 6;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { h } from 'preact';
import { useContext } from 'preact/hooks';

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

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

// register with the visibility menu
Expand Down
14 changes: 14 additions & 0 deletions special-pages/pages/new-tab/app/favorites/strings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"favorites_show_less": {
"title": "Show less",
"note": "Button label to display fewer items"
},
"favorites_show_more": {
"title": "Show more ({count} remaining)",
"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)'"
},
"favorites_menu_title": {
"title": "Favorites",
"note": "Used as a label in a customization menu"
}
}
2 changes: 1 addition & 1 deletion special-pages/pages/new-tab/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { SettingsProvider } from './settings.provider.js';
import { InitialSetupContext, MessagingContext, TelemetryContext } from './types';
import { TranslationProvider } from '../../../shared/components/TranslationsProvider.js';
import { WidgetConfigService } from './widget-list/widget-config.service.js';
import enStrings from '../src/locales/en/newtab.json';
import enStrings from '../src/locales/en/new-tab.json';
import { WidgetConfigProvider } from './widget-list/widget-config.provider.js';
import { Settings } from './settings.js';
import { Components } from './components/Components.jsx';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { TestTransportConfig } from '@duckduckgo/messaging';

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

/**
* @typedef {import('../../../../types/new-tab').Favorite} Favorite
* @typedef {import('../../../../types/new-tab').FavoritesData} FavoritesData
* @typedef {import('../../../../types/new-tab').FavoritesConfig} FavoritesConfig
* @typedef {import('../../../../types/new-tab').StatsConfig} StatsConfig
* @typedef {import('../../../../types/new-tab').NextStepsConfig} NextStepsConfig
* @typedef {import('../../../../types/new-tab').NextStepsCards} NextStepsCards
* @typedef {import('../../../../types/new-tab').NextStepsData} NextStepsData
* @typedef {import('../../../../types/new-tab').UpdateNotificationData} UpdateNotificationData
* @typedef {import('../../../../types/new-tab.js').NewTabMessages['subscriptions']['subscriptionEvent']} SubscriptionNames
* @typedef {import('../../../types/new-tab').Favorite} Favorite
* @typedef {import('../../../types/new-tab').FavoritesData} FavoritesData
* @typedef {import('../../../types/new-tab').FavoritesConfig} FavoritesConfig
* @typedef {import('../../../types/new-tab').StatsConfig} StatsConfig
* @typedef {import('../../../types/new-tab').NextStepsConfig} NextStepsConfig
* @typedef {import('../../../types/new-tab').NextStepsCards} NextStepsCards
* @typedef {import('../../../types/new-tab').NextStepsData} NextStepsData
* @typedef {import('../../../types/new-tab').UpdateNotificationData} UpdateNotificationData
* @typedef {import('../../../types/new-tab').NewTabMessages['subscriptions']['subscriptionEvent']} SubscriptionNames
*/

const VERSION_PREFIX = '__ntp_28__.';
const VERSION_PREFIX = '__ntp_29__.';
const url = new URL(window.location.href);

export function mockTransport() {
Expand Down Expand Up @@ -75,7 +75,7 @@

function clearRmf() {
const listeners = rmfSubscriptions.get('rmf_onDataUpdate') || [];
/** @type {import('../../../../types/new-tab.js').RMFData} */
/** @type {import('../../../types/new-tab.ts').RMFData} */
const message = { content: undefined };
for (const listener of listeners) {
listener(message);
Expand All @@ -85,7 +85,7 @@
return new TestTransportConfig({
notify(_msg) {
window.__playwright_01?.mocks?.outgoing?.push?.({ payload: structuredClone(_msg) });
/** @type {import('../../../../types/new-tab.js').NewTabMessages['notifications']} */
/** @type {import('../../../types/new-tab.ts').NewTabMessages['notifications']} */
const msg = /** @type {any} */ (_msg);
switch (msg.method) {
case 'widgets_setConfig': {
Expand Down Expand Up @@ -154,7 +154,7 @@
},
subscribe(_msg, cb) {
window.__playwright_01?.mocks?.outgoing?.push?.({ payload: structuredClone(_msg) });
/** @type {import('../../../../types/new-tab.js').NewTabMessages['subscriptions']['subscriptionEvent']} */
/** @type {import('../../../types/new-tab.ts').NewTabMessages['subscriptions']['subscriptionEvent']} */
const sub = /** @type {any} */ (_msg.subscriptionName);
switch (sub) {
case 'widgets_onConfigUpdated': {
Expand Down Expand Up @@ -303,7 +303,7 @@
// eslint-ignore-next-line require-await
request(_msg) {
window.__playwright_01?.mocks?.outgoing?.push?.({ payload: structuredClone(_msg) });
/** @type {import('../../../../types/new-tab.js').NewTabMessages['requests']} */
/** @type {import('../../../types/new-tab.ts').NewTabMessages['requests']} */
const msg = /** @type {any} */ (_msg);
switch (msg.method) {
case 'stats_getData': {
Expand Down Expand Up @@ -346,14 +346,14 @@
return true;
})
.map((id) => {
return { id: /** @type {any} */ (id) };

Check warning on line 349 in special-pages/pages/new-tab/app/mock-transport.js

View workflow job for this annotation

GitHub Actions / unit (ubuntu-latest)

Expected property shorthand

Check warning on line 349 in special-pages/pages/new-tab/app/mock-transport.js

View workflow job for this annotation

GitHub Actions / unit (windows-latest)

Expected property shorthand
}),
};
}
return Promise.resolve(data);
}
case 'rmf_getData': {
/** @type {import('../../../../types/new-tab.js').RMFData} */
/** @type {import('../../../types/new-tab.ts').RMFData} */
let message = { content: undefined };
const rmfParam = url.searchParams.get('rmf');

Expand Down Expand Up @@ -414,7 +414,7 @@
updateNotification = updateNotificationExamples.populated;
}

/** @type {import('../../../../types/new-tab.js').InitialSetupResponse} */
/** @type {import('../../../types/new-tab.ts').InitialSetupResponse} */
const initial = {
widgets: widgetsFromStorage,
widgetConfigs: widgetConfigFromStorage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { h } from 'preact';
import styles from './NextSteps.module.css';
import { DismissButton } from '../../components/DismissButton';
import { variants } from '../nextsteps.data';
import { useTypedTranslation } from '../../types';
import { useTypedTranslationWith } from '../../types';

/**
* @param {object} props
Expand All @@ -12,7 +12,7 @@ import { useTypedTranslation } from '../../types';
*/

export function NextStepsCard({ type, dismiss, action }) {
const { t } = useTypedTranslation();
const { t } = useTypedTranslationWith(/** @type {import("../strings.json")} */ ({}));
const message = variants[type]?.(t);
return (
<div class={styles.card}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { h } from 'preact';
import cn from 'classnames';
import styles from './NextSteps.module.css';
import { useTypedTranslation } from '../../types';
import { useTypedTranslationWith } from '../../types';
import { NextStepsCard } from './NextStepsCard';
import { otherText } from '../nextsteps.data';
import { ShowHideButton } from '../../components/ShowHideButton';
import { useId } from 'preact/hooks';

/**
* @import enStrings from '../strings.json';
* @import ntpStrings from '../../strings.json';
* @typedef {enStrings & ntpStrings} strings
* @typedef {import('../../../../../types/new-tab').Expansion} Expansion
* @typedef {import('../../../../../types/new-tab').Animation} Animation
* @typedef {import('../../../../../types/new-tab').NextStepsCards} NextStepsCards
Expand All @@ -22,7 +25,7 @@ import { useId } from 'preact/hooks';
* @param {(id: string)=>void} props.dismiss
*/
export function NextStepsCardGroup({ types, expansion, toggle, action, dismiss }) {
const { t } = useTypedTranslation();
const { t } = useTypedTranslationWith(/** @type {strings} */ ({}));
const WIDGET_ID = useId();
const TOGGLE_ID = useId();
const alwaysShown = types.length > 2 ? types.slice(0, 2) : types;
Expand Down Expand Up @@ -63,7 +66,7 @@ export function NextStepsCardGroup({ types, expansion, toggle, action, dismiss }
}

export function NextStepsBubbleHeader() {
const { t } = useTypedTranslation();
const { t } = useTypedTranslationWith(/** @type {strings} */ ({}));
const text = otherText.nextSteps_sectionTitle(t);
return (
<div class={styles.bubble}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ test.describe('newtab NextSteps cards', () => {
await expect(page.getByRole('button', { name: 'Try DuckPlayer' })).not.toBeVisible();

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

await expect(page.locator('p').filter({ hasText: 'Block Cookie Pop-ups' })).toBeVisible();
await page.getByRole('button', { name: 'Try DuckPlayer' }).click();
Expand Down
24 changes: 14 additions & 10 deletions special-pages/pages/new-tab/app/next-steps/nextsteps.data.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,57 @@
/**
* @import enStrings from "./strings.json"
* @import ntpStrings from "../strings.json"
*/
export const variants = {
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof enStrings) => string} t */
bringStuff: (t) => ({
id: 'bringStuff',
icon: 'Bring-Stuff',
title: t('nextSteps_bringStuff_title'),
summary: t('nextSteps_bringStuff_summary'),
actionText: t('nextSteps_bringStuff_actionText'),
}),
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof enStrings) => string} t */
defaultApp: (t) => ({
id: 'defaultApp',
icon: 'Default-App',
title: t('nextSteps_defaultApp_title'),
summary: t('nextSteps_defaultApp_summary'),
actionText: t('nextSteps_defaultApp_actionText'),
}),
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof enStrings) => string} t */
blockCookies: (t) => ({
id: 'blockCookies',
icon: 'Cookie-Pops',
title: t('nextSteps_blockCookies_title'),
summary: t('nextSteps_blockCookies_summary'),
actionText: t('nextSteps_blockCookies_actionText'),
}),
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof enStrings) => string} t */
emailProtection: (t) => ({
id: 'emailProtection',
icon: 'Email-Protection',
title: t('nextSteps_emailProtection_title'),
summary: t('nextSteps_emailProtection_summary'),
actionText: t('nextSteps_emailProtection_actionText'),
}),
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof enStrings) => string} t */
duckplayer: (t) => ({
id: 'duckplayer',
icon: 'Tube-Clean',
title: t('nextSteps_duckPlayer_title'),
summary: t('nextSteps_duckPlayer_summary'),
actionText: t('nextSteps_duckPlayer_actionText'),
}),
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof enStrings) => string} t */
addAppToDockMac: (t) => ({
id: 'addAppToDockMac',
icon: 'Dock-Add-Mac',
title: t('nextSteps_addAppDockMac_title'),
summary: t('nextSteps_addAppDockMac_summary'),
actionText: t('nextSteps_addAppDockMac_actionText'),
}),
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof enStrings) => string} t */
pinAppToTaskbarWindows: (t) => ({
id: 'pinAppToTaskbarWindows',
icon: 'Dock-Add-Windows',
Expand All @@ -58,10 +62,10 @@ export const variants = {
};

export const otherText = {
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof ntpStrings) => string} t */
showMore: (t) => t('ntp_show_more'),
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof ntpStrings) => string} t */
showLess: (t) => t('ntp_show_less'),
/** @param {(translationId: string) => string} t */
/** @param {(translationId: keyof enStrings) => string} t */
nextSteps_sectionTitle: (t) => t('nextSteps_sectionTitle'),
};
Loading
Loading