Skip to content

Commit

Permalink
Merge pull request #984 from WatWowMap/locales-editing-page
Browse files Browse the repository at this point in the history
feat: locales editing page
  • Loading branch information
TurtIeSocks authored Mar 16, 2024
2 parents 6a9eec6 + b259e42 commit 01570c2
Show file tree
Hide file tree
Showing 21 changed files with 462 additions and 29 deletions.
16 changes: 15 additions & 1 deletion packages/locales/lib/human/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -765,5 +765,19 @@
"reset_spawnpoints": "Reset Spawnpoints",
"reset_submission_cells": "Reset Submission Cells",
"hisuian": "Hisuian",
"spacial_rend_range": "Spacial Rend Range"
"spacial_rend_range": "Spacial Rend Range",
"key": "Key",
"ai": "AI",
"human": "Human",
"locales": "Locales",
"instructions": "Instructions",
"locale_instructions_1": "Select a language from the dropdown",
"locale_instructions_2": "Enter the desired translations in the \"Human\" column",
"locale_instructions_3": "Click the \"$t(download)\" button to download a JSON file",
"locale_instructions_4": "Fork the GitHub repo link below",
"locale_instructions_5": "Create a new branch and name it the language you are translating",
"locale_instructions_6": "Replace the contents of \"packages/locales/lib/human/{{lng}}.json\" with the file you downloaded",
"locale_instructions_7": "Create a pull request",
"locale_instructions_8": "Wait for the pull request to be reviewed and merged",
"enter_translation": "Enter Translation"
}
8 changes: 7 additions & 1 deletion packages/locales/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
const { create } = require('./create')
const { missing } = require('./missing')
const { generate } = require('./generate')
const { readLocaleDirectory, writeAll, getStatus } = require('./utils')
const {
readLocaleDirectory,
writeAll,
getStatus,
readAndParseJson,
} = require('./utils')

const locales = readLocaleDirectory(true).map((x) => x.replace('.json', ''))
const status = getStatus()
Expand All @@ -12,3 +17,4 @@ module.exports.create = create
module.exports.missing = missing
module.exports.generate = generate
module.exports.writeAll = writeAll
module.exports.readAndParseJson = readAndParseJson
43 changes: 25 additions & 18 deletions packages/locales/lib/missing.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,34 @@ const { resolve } = require('path')
const { log, HELPERS } = require('@rm/logger')
const { readAndParseJson, readLocaleDirectory } = require('./utils')

async function missing() {
const localTranslations = readLocaleDirectory(true)
/**
*
* @param {string} fileName
* @returns {Promise<import('./generate').I18nObject>}
*/
async function missing(fileName) {
const englishRef = await readAndParseJson('en.json', true)
const humanLocales = await readAndParseJson(fileName, true)
/** @type {import('./generate').I18nObject} */
const missingKeys = {}

await Promise.allSettled(
localTranslations.map(async (fileName) => {
const humanLocales = await readAndParseJson(fileName, true)
const aiLocales = await readAndParseJson(fileName, false)
const combined = {
...aiLocales,
...humanLocales,
Object.keys(englishRef)
.sort()
.forEach((key) => {
if (!humanLocales[key] && !key.startsWith('locale_selection_')) {
missingKeys[key] = process.argv.includes('--ally')
? `t('${key}')`
: englishRef[key]
}
const missingKeys = {}
})
return missingKeys
}

Object.keys(englishRef).forEach((key) => {
if (!combined[key] && !key.startsWith('locale_selection_')) {
missingKeys[key] = process.argv.includes('--ally')
? `t('${key}')`
: englishRef[key]
}
})
async function missingAll() {
const localTranslations = readLocaleDirectory(true)
await Promise.allSettled(
localTranslations.map(async (fileName) => {
const missingKeys = await missing(fileName)
await fs.writeFile(
resolve(
__dirname,
Expand All @@ -44,5 +51,5 @@ async function missing() {
module.exports.missing = missing

if (require.main === module) {
missing().then(() => process.exit(0))
missingAll().then(() => process.exit(0))
}
10 changes: 5 additions & 5 deletions packages/locales/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,14 @@ function getStatus() {
),
)
const mergedSize = Object.keys({ ...aiJson, ...humanJson }).length
const human = +(humanHas / total).toFixed(2) * 100
const localeTotal = Math.min(1, +(mergedSize / total).toFixed(2)) * 100
const human = (humanHas / total) * 100
const localeTotal = (mergedSize / total) * 100
return [
locale.replace('.json', ''),
{
human,
ai: localeTotal - human,
total: localeTotal,
human: Math.round(human),
ai: Math.round(localeTotal - human),
total: Math.round(localeTotal),
},
]
}),
Expand Down
11 changes: 11 additions & 0 deletions server/src/graphql/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { resolve } = require('path')
const { GraphQLJSON } = require('graphql-type-json')
const { S2LatLng, S2RegionCoverer, S2LatLngRect } = require('nodes2ts')
const config = require('@rm/config')
const { missing, readAndParseJson } = require('@rm/locales')

const buildDefaultFilters = require('../services/filters/builder/base')
const filterComponents = require('../services/functions/filterComponents')
Expand Down Expand Up @@ -198,6 +199,16 @@ const resolvers = {
}
return {}
},
locales: async (_, { locale }) => {
const missingLocales = await missing(`${locale}.json`)
return locale
? {
missing: Object.keys(missingLocales),
human: await readAndParseJson(`${locale}.json`, true),
ai: await readAndParseJson(`${locale}.json`, false),
}
: { missing: null, human: null, ai: null }
},
motdCheck: (_, { clientIndex }, { req, perms }) => {
const motd = config.getMapConfig(req).messageOfTheDay
return (
Expand Down
1 change: 1 addition & 0 deletions server/src/graphql/typeDefs/index.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Query {
filters: JSON
): [Gym]
gymsSingle(id: ID, perm: String): Gym
locales(locale: String): Locales
motdCheck(clientIndex: Int): Boolean
nests(
minLat: Float
Expand Down
6 changes: 6 additions & 0 deletions server/src/graphql/typeDefs/map.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,9 @@ type ValidUserObj {
loggedIn: Boolean
admin: Boolean
}

type Locales {
human: JSON
ai: JSON
missing: JSON
}
7 changes: 4 additions & 3 deletions server/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,13 @@ startApollo(httpServer).then((server) => {
const definition = parse(req.body.query).definitions.find(
(d) => d.kind === 'OperationDefinition',
)
const endpoint = definition?.name?.value || ''
const errorCtx = {
id,
user,
clientV,
serverV,
endpoint: definition.name?.value || '',
endpoint,
}

if (clientV && serverV && clientV !== serverV) {
Expand All @@ -262,7 +263,7 @@ startApollo(httpServer).then((server) => {
})
}

if (!perms) {
if (!perms && endpoint !== 'Locales') {
throw new GraphQLError('session_expired', {
extensions: {
...errorCtx,
Expand All @@ -275,7 +276,7 @@ startApollo(httpServer).then((server) => {
if (
definition?.operation === 'mutation' &&
!id &&
definition?.name?.value !== 'SetTutorial'
endpoint !== 'SetTutorial'
) {
throw new GraphQLError('unauthenticated', {
extensions: {
Expand Down
2 changes: 2 additions & 0 deletions server/src/routes/clientRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const CLIENT_ROUTES = [
'/500',
'/reset',
'/playground',
'/locales',
'/data-management',
]

router.get(CLIENT_ROUTES, (req, res) => {
Expand Down
6 changes: 6 additions & 0 deletions src/assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -554,3 +554,9 @@ input[type='time']::-webkit-calendar-picker-indicator {
opacity: 90%;
z-index: 9;
}

.locales-layout {
display: grid;
grid-template-rows: auto 1fr auto; /* Header, table, footer */
min-height: 100svh;
}
31 changes: 31 additions & 0 deletions src/components/virtual/Table.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from 'react'
import Table from '@mui/material/Table'
import TableBody from '@mui/material/TableBody'
import TableContainer from '@mui/material/TableContainer'
import TableHead from '@mui/material/TableHead'
import TableRow from '@mui/material/TableRow'
import Paper from '@mui/material/Paper'
import { TableVirtuoso } from 'react-virtuoso'

const COMPONENTS = {
Scroller: React.forwardRef((props, ref) => (
<TableContainer component={Paper} {...props} ref={ref} />
)),
Table: (props) => (
<Table
{...props}
sx={{ borderCollapse: 'separate', tableLayout: 'fixed' }}
/>
),
TableHead,
// eslint-disable-next-line no-unused-vars
TableRow: ({ item: _, ...props }) => <TableRow {...props} />,
TableBody: React.forwardRef((props, ref) => (
<TableBody {...props} ref={ref} />
)),
}

/** @param {import('react-virtuoso').TableVirtuosoProps} props */
export function VirtualTable(props) {
return <TableVirtuoso components={COMPONENTS} {...props} />
}
3 changes: 3 additions & 0 deletions src/pages/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { BlockedPage } from './Blocked'
import { ErrorPage } from './Error'
import { DataManagerPage } from './data'
import { ResetPage } from './Reset'
import { LocalesPage } from './locales'

const Playground = React.lazy(() =>
import('./playground').then(({ PlaygroundPage }) => ({
Expand Down Expand Up @@ -44,6 +45,7 @@ const playgroundRoute = (
)
const errorRoute = <ErrorPage />
const resetRoute = <ResetPage />
const localesPage = <LocalesPage />

export function Pages() {
return (
Expand All @@ -52,6 +54,7 @@ export function Pages() {
<Route path="reset" element={resetRoute} />
<Route path="login" element={loginRoute} />
<Route path="data-management" element={dataRoute} />
<Route path="locales" element={localesPage} />
<Route path="playground" element={playgroundRoute} />
<Route path="blocked/:info" element={blockedRoute} />
<Route path="@/:lat/:lon" element={mapRoute} />
Expand Down
22 changes: 22 additions & 0 deletions src/pages/locales/components/AllSwitch.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as React from 'react'
import FormControlLabel from '@mui/material/FormControlLabel'
import Switch from '@mui/material/Switch'
import { useTranslation } from 'react-i18next'

import { useLocalesStore } from '../hooks/store'

export function AllSwitch() {
const { t } = useTranslation()
const all = useLocalesStore((s) => s.all)
return (
<FormControlLabel
control={
<Switch
checked={all}
onChange={(_, checked) => useLocalesStore.setState({ all: checked })}
/>
}
label={t('all')}
/>
)
}
37 changes: 37 additions & 0 deletions src/pages/locales/components/EditLocale.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// @ts-check
import * as React from 'react'
import TextField from '@mui/material/TextField'
import { useTranslation } from 'react-i18next'

import { useLocalesStore } from '../hooks/store'

/** @param {{ name: string } & import('@mui/material').TextFieldProps} props */
export function EditLocale({ name, type, ...props }) {
const { t } = useTranslation()
const value = useLocalesStore((s) => s.custom[name] || '')
/** @type {import('@mui/material').TextFieldProps['onChange']} */
const onChange = React.useCallback(
(event) => {
useLocalesStore.setState((prev) => ({
custom: {
...prev.custom,
[name]:
type === 'number' ? +event.target.value || 0 : event.target.value,
},
}))
},
[name],
)
return (
<TextField
fullWidth
type={type}
value={value}
onChange={onChange}
multiline={type === 'text'}
size="small"
placeholder={t('enter_translation')}
{...props}
/>
)
}
35 changes: 35 additions & 0 deletions src/pages/locales/components/LocalesFooter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// @ts-check
import * as React from 'react'
import Grid from '@mui/material/Unstable_Grid2'
import Button from '@mui/material/Button'
import GitHubIcon from '@mui/icons-material/GitHub'
import { useTranslation } from 'react-i18next'

import { downloadLocales } from '../hooks/store'
import { AllSwitch } from './AllSwitch'

const github = <GitHubIcon />

export function LocalesFooter() {
const { t } = useTranslation()
return (
<Grid component="footer" container justifyContent="space-evenly" py={1}>
<Grid xs={4} sm={2} className="flex-center">
<AllSwitch />
</Grid>
<Grid xs={4} sm={2} className="flex-center">
<Button onClick={downloadLocales}>{t('download')}</Button>
</Grid>
<Grid xs={4} sm={2} className="flex-center">
<Button
startIcon={github}
color="secondary"
href="https://github.com/WatWowMap/ReactMap"
target="_blank"
>
{t('contribute')}
</Button>
</Grid>
</Grid>
)
}
Loading

0 comments on commit 01570c2

Please sign in to comment.