fix: internationalize manifest.json (#2034)
* fix: internationalize manifest.json fixes #2020 * test: fix test
This commit is contained in:
parent
66fc202b5c
commit
85a5874876
|
@ -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
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
26
bin/getIntl.js
Normal file
26
bin/getIntl.js
Normal file
|
@ -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, ' ')
|
||||
}
|
|
@ -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": [
|
||||
{
|
|
@ -27,6 +27,9 @@ export default {
|
|||
Here is the <a href="/settings/about#privacy-policy" rel="prefetch">privacy policy</a>.
|
||||
</p>
|
||||
`,
|
||||
// Manifest
|
||||
longAppName: 'Pinafore for Mastodon',
|
||||
newStatus: 'New toot',
|
||||
// Generic UI
|
||||
loading: 'Loading',
|
||||
okay: 'OK',
|
||||
|
|
|
@ -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": "/"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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') }))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue