From 85a58748766e477c67552e7e1ceaea6fa40eea4b Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Sun, 11 Apr 2021 19:40:24 -0700 Subject: [PATCH] fix: internationalize manifest.json (#2034) * fix: internationalize manifest.json fixes #2020 * test: fix test --- .dockerignore | 1 + .gitignore | 1 + .vercelignore | 1 + bin/build-assets.js | 23 +++++++++++++++++- bin/getIntl.js | 26 ++++++++++++++++++++ {static => src/build}/manifest.json | 14 ++++------- src/intl/en-US.js | 3 +++ static/manifest.webapp | 37 ----------------------------- tests/unit/test-intl.js | 2 +- webpack/svelte-intl-loader.js | 27 +-------------------- 10 files changed, 61 insertions(+), 74 deletions(-) create mode 100644 bin/getIntl.js rename {static => src/build}/manifest.json (88%) delete mode 100644 static/manifest.webapp diff --git a/.dockerignore b/.dockerignore index 0afcc6d6..ea125821 100644 --- a/.dockerignore +++ b/.dockerignore @@ -14,6 +14,7 @@ tests /static/icons.svg /static/inline-script.js.map /static/emoji-*.json +/static/manifest.json /src/inline-script/checksum.js yarn-error.log /vercel.json diff --git a/.gitignore b/.gitignore index b54333be..4e191c72 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ /static/icons.svg /static/inline-script.js.map /static/emoji-*.json +/static/manifest.json /src/inline-script/checksum.js yarn-error.log diff --git a/.vercelignore b/.vercelignore index 155e569b..4b0e700b 100644 --- a/.vercelignore +++ b/.vercelignore @@ -8,5 +8,6 @@ /static/icons.svg /static/inline-script.js.map /static/emoji-*.json +/static/manifest.json /src/inline-script/checksum.js yarn-error.log diff --git a/bin/build-assets.js b/bin/build-assets.js index 5dc271e0..dbd71a27 100644 --- a/bin/build-assets.js +++ b/bin/build-assets.js @@ -2,6 +2,7 @@ import path from 'path' import fs from 'fs' import { promisify } from 'util' import { LOCALE } from '../src/routes/_static/intl' +import { getIntl, trimWhitespace } from './getIntl' const readFile = promisify(fs.readFile) const writeFile = promisify(fs.writeFile) @@ -34,7 +35,7 @@ async function getFirstExistingEmojiI18nFile () { } } -async function main () { +async function buildEmojiI18nFile () { const json = await getFirstExistingEmojiI18nFile() if (!json) { @@ -48,6 +49,26 @@ async function main () { ) } +async function buildManifestJson () { + const template = await readFile(path.resolve(__dirname, '../src/build/manifest.json'), 'utf8') + // replace {@intl.foo} + const output = template + .replace(/{intl\.([^}]+)}/g, (match, p1) => trimWhitespace(getIntl(p1))) + + await writeFile( + path.resolve(__dirname, '../static/manifest.json'), + JSON.stringify(JSON.parse(output)), // minify json + 'utf8' + ) +} + +async function main () { + await Promise.all([ + buildEmojiI18nFile(), + buildManifestJson() + ]) +} + main().catch(err => { console.error(err) process.exit(1) diff --git a/bin/getIntl.js b/bin/getIntl.js new file mode 100644 index 00000000..519c075e --- /dev/null +++ b/bin/getIntl.js @@ -0,0 +1,26 @@ +import { get } from 'lodash-es' +import { DEFAULT_LOCALE, LOCALE } from '../src/routes/_static/intl' +import path from 'path' + +const intl = require(path.join(__dirname, '../src/intl', LOCALE + '.js')).default +const defaultIntl = require(path.join(__dirname, '../src/intl', DEFAULT_LOCALE + '.js')).default + +export function warningOrError (message) { // avoid crashing the whole server on `yarn dev` + if (process.env.NODE_ENV === 'production') { + throw new Error(message) + } + console.warn(message) + return '(Placeholder intl string)' +} + +export function getIntl (path) { + const res = get(intl, path, get(defaultIntl, path)) + if (typeof res !== 'string') { + return warningOrError('Unknown intl string: ' + JSON.stringify(path)) + } + return res +} + +export function trimWhitespace (str) { + return str.trim().replace(/\s+/g, ' ') +} diff --git a/static/manifest.json b/src/build/manifest.json similarity index 88% rename from static/manifest.json rename to src/build/manifest.json index 99eaa855..a50b6f56 100644 --- a/static/manifest.json +++ b/src/build/manifest.json @@ -1,9 +1,9 @@ { "background_color": "#ffffff", "theme_color": "#4169e1", - "name": "Pinafore for Mastodon", - "short_name": "Pinafore", - "description": "Alternative web client for Mastodon, focused on speed and simplicity.", + "name": "{intl.longAppName}", + "short_name": "{intl.appName}", + "description": "{intl.appDescription}", "categories": [ "social" ], @@ -114,9 +114,7 @@ ], "shortcuts": [ { - "name": "Write a toot", - "short_name": "New toot", - "description": "Start composing a new toot", + "name": "{intl.newStatus}", "url": "/?pwa=true&compose=true", "icons": [ { @@ -126,9 +124,7 @@ ] }, { - "name": "View notifications", - "short_name": "Notifications", - "description": "View your new notifications", + "name": "{intl.notifications}", "url": "/notifications?pwa=true", "icons": [ { diff --git a/src/intl/en-US.js b/src/intl/en-US.js index 3999afeb..2a041db5 100644 --- a/src/intl/en-US.js +++ b/src/intl/en-US.js @@ -27,6 +27,9 @@ export default { Here is the privacy policy.

`, + // Manifest + longAppName: 'Pinafore for Mastodon', + newStatus: 'New toot', // Generic UI loading: 'Loading', okay: 'OK', diff --git a/static/manifest.webapp b/static/manifest.webapp deleted file mode 100644 index 4fff47e3..00000000 --- a/static/manifest.webapp +++ /dev/null @@ -1,37 +0,0 @@ -{ - "version": "1.0.0", - "name": "Pinafore", - "description": "Mastodon client", - "type": "web", - "launch_path": "/", - "icons": { - "48": "/icon-48.png", - "72": "/icon-72.png", - "96": "/icon-96.png" - }, - "developer": { - "name": "Nolan Lawson", - "url": "https://nolanlawson.com" - }, - "locales": { - "en-US": { - "name": "Pinafore", - "subtitle": "Mastodon client", - "description": "Mastodon client, focused on speed and simplicity." - } - }, - "default_locale": "en-US", - "permissions": { - "serviceworker": { - "description": "Needed for offline storage and notifications." - }, - "desktop-notification": { - "description": "Needed for notifications." - } - }, - "messages": [ - { - "serviceworker-notification": "/" - } - ] -} diff --git a/tests/unit/test-intl.js b/tests/unit/test-intl.js index 89533cda..4ab23236 100644 --- a/tests/unit/test-intl.js +++ b/tests/unit/test-intl.js @@ -16,7 +16,7 @@ describe('test-intl.js', () => { it('has no unused intl strings', async () => { const keys = Object.keys(enIntl) - const allSourceFilenames = (await globby([path.join(__dirname, '../../src/**/*.{js,html}')])) + const allSourceFilenames = (await globby([path.join(__dirname, '../../src/**/*.{js,html,json}')])) .filter(file => !file.includes('/intl/')) const allSourceFiles = await Promise.all( allSourceFilenames.map(async name => ({ name, content: await readFile(name, 'utf8') })) diff --git a/webpack/svelte-intl-loader.js b/webpack/svelte-intl-loader.js index 18456da2..a77d2028 100644 --- a/webpack/svelte-intl-loader.js +++ b/webpack/svelte-intl-loader.js @@ -1,32 +1,7 @@ // Inject intl statements into a Svelte v2 HTML file as well as some JS files like timeago.js // We do this for perf reasons, to make the output smaller and avoid needing to have a huge JSON file of translations -import { get } from 'lodash-es' import parse from 'format-message-parse' -import { DEFAULT_LOCALE, LOCALE } from '../src/routes/_static/intl' -import path from 'path' - -const intl = require(path.join(__dirname, '../src/intl', LOCALE + '.js')).default -const defaultIntl = require(path.join(__dirname, '../src/intl', DEFAULT_LOCALE + '.js')).default - -function warningOrError (message) { // avoid crashing the whole server on `yarn dev` - if (process.env.NODE_ENV === 'production') { - throw new Error(message) - } - console.warn(message) - return '(Placeholder intl string)' -} - -function getIntl (path) { - const res = get(intl, path, get(defaultIntl, path)) - if (typeof res !== 'string') { - return warningOrError('Unknown intl string: ' + JSON.stringify(path)) - } - return res -} - -function trimWhitespace (str) { - return str.trim().replace(/\s+/g, ' ') -} +import { getIntl, warningOrError, trimWhitespace } from '../bin/getIntl' export default function (source) { const res = source