Finished translations / bug fixes

This commit is contained in:
Sebastian Seedorf
2022-08-20 14:47:04 +02:00
parent 664f766cb6
commit 2fd010e003
13 changed files with 162 additions and 66 deletions

View File

@@ -49,6 +49,10 @@
{
"additionalHooks": "(useAsyncEffect)"
}
],
"react/jsx-no-literals": [
"error",
{ "noStrings": true, "allowedStrings": [], "ignoreProps": true, "noAttributeStrings": false }
]
},
"overrides": [

View File

@@ -33,7 +33,7 @@ interface GroupContextType {
setBaseFactories(factories: string[]): void
groups: Dict<Group>
addGroup(name: string, exported?: string[], malls?: string[]): void
addGroup(name: string, exported?: string[], malls?: string[]): boolean
removeGroup(name: string): void
renameGroup(name: string, newName: string): void
@@ -60,7 +60,7 @@ const defaultValues: GroupContextType = {
groups: {},
addGroup() {
return
return false
},
removeGroup() {
return
@@ -174,7 +174,7 @@ export const GroupProvider: FC<Props> = ({ children, id, initial }) => {
`/api/${fixedEncodeURIComponent(id)}/group/${fixedEncodeURIComponent(name)}/factories`,
{
type: 'malls',
factories: exports
factories: malls
} as GroupSetFactoryArrayBody
)
}

View File

@@ -2,10 +2,11 @@ import { FC, HTMLProps, memo, useMemo } from 'react'
import { EnrichedEntity } from '../../../src/types'
import styles from './EntitySpan.module.css'
import { RecipeSpan } from '../Recipe/Recipe'
import { LeftClickIcon } from '../LeftClickIcon/LeftClickIcon'
import { LeftClickIcon } from '../../icons/LeftClickIcon'
import cx from 'classnames'
import { EntityIcon } from '../EntityIcon/EntityIcon'
import { useFactories } from '../../contexts/FactoryProvider'
import { I18n } from '../../shared/I18n/I18n'
interface Props extends Omit<HTMLProps<HTMLSpanElement>, 'value'> {
value: EnrichedEntity | string
@@ -16,7 +17,7 @@ interface Props extends Omit<HTMLProps<HTMLSpanElement>, 'value'> {
className?: string
}
const EntitySpanUnmemo: FC<Props> = ({
const EntitySpanBase: FC<Props> = ({
className,
value,
state,
@@ -50,13 +51,17 @@ const EntitySpanUnmemo: FC<Props> = ({
<div className={styles.tooltip}>
{entity.recipe && (
<>
<div className={styles.strong}>Recipe</div>
<div className={styles.strong}>
<I18n id={'page.home.tooltip.recipe'} />
</div>
<RecipeSpan recipe={entity.recipe} />
</>
)}
{entity.usedBy?.length ? (
<>
<div className={styles.strong}>Used By</div>
<div className={styles.strong}>
<I18n id={'page.home.tooltip.used_by'} />
</div>
<div className={styles.usedBy}>
{entity.usedBy.map(used => (
<EntityIcon value={used} key={used.name} />
@@ -66,7 +71,9 @@ const EntitySpanUnmemo: FC<Props> = ({
) : null}
{(leftClickText || rightClickText) && (
<>
<div className={styles.strong}>Actions</div>
<div className={styles.strong}>
<I18n id={'page.home.tooltip.actions'} />
</div>
{leftClickText && (
<div>
<LeftClickIcon className={styles.leftClick} classClick={styles.clickBtn} />{' '}
@@ -86,4 +93,4 @@ const EntitySpanUnmemo: FC<Props> = ({
)
}
export const EntitySpan = memo(EntitySpanUnmemo)
export const EntitySpan = memo(EntitySpanBase)

View File

@@ -11,6 +11,7 @@ import { useRouter } from 'next/router'
import { useFactories } from '../../contexts/FactoryProvider'
import { i18n, I18n } from '../../shared/I18n/I18n'
import { useIntl } from 'react-intl'
import { GraphIcon } from '../../icons/GraphIcon'
interface Props {
group: Group
@@ -94,7 +95,9 @@ const GroupBoxBase: FC<Props> = ({ group }) => {
query
}}
>
👁
<a>
<GraphIcon />
</a>
</Link>
<button
className={styles.quit}
@@ -119,7 +122,7 @@ const GroupBoxBase: FC<Props> = ({ group }) => {
{inputs.length ? (
<>
<h4>
<I18n id={'page.home.group.item.input'} /> ({inputs.length})
<I18n id={'page.home.group.item.input'} values={{ amount: inputs.length }} />
</h4>
<div className={styles.flex}>
{inputs.map(input => (
@@ -131,7 +134,7 @@ const GroupBoxBase: FC<Props> = ({ group }) => {
event.preventDefault()
setIgnoredFactories([...ignoredFactories, input])
}}
rightClickText={'Exclude this recipe from suggestions'}
rightClickText={i18n(intl, 'page.home.tooltip.action.exclude_suggestion')}
/>
))}
</div>
@@ -140,7 +143,10 @@ const GroupBoxBase: FC<Props> = ({ group }) => {
{intermediates.length ? (
<>
<h4>
<I18n id={'page.home.group.item.intermediate'} /> ({intermediates.length})
<I18n
id={'page.home.group.item.intermediate'}
values={{ amount: intermediates.length }}
/>
</h4>
<div className={styles.flex}>
{intermediates.map(intermediate => (
@@ -168,8 +174,8 @@ const GroupBoxBase: FC<Props> = ({ group }) => {
event.preventDefault()
setIgnoredFactories([...ignoredFactories, suggestion.href])
}}
leftClickText={'Add to exported factories'}
rightClickText={'Exclude this recipe from suggestions'}
leftClickText={i18n(intl, 'page.home.tooltip.action.add_to_export')}
rightClickText={i18n(intl, 'page.home.tooltip.action.exclude_suggestion')}
/>
))}
</div>
@@ -190,8 +196,8 @@ const GroupBoxBase: FC<Props> = ({ group }) => {
event.preventDefault()
setIgnoredFactories([...ignoredFactories, suggestion.href])
}}
leftClickText={'Add to mall factories'}
rightClickText={'Exclude this recipe from suggestions'}
leftClickText={i18n(intl, 'page.home.tooltip.action.add_to_mall')}
rightClickText={i18n(intl, 'page.home.tooltip.action.exclude_suggestion')}
/>
))}
</div>

View File

@@ -1,4 +1,4 @@
import { FC, useMemo, useRef, useState } from 'react'
import { ElementRef, FC, useMemo, useRef } from 'react'
import { GroupBox } from './GroupBox/GroupBox'
import styles from './Home.module.css'
import { EnrichedEntity } from '../../src/types'
@@ -8,15 +8,17 @@ import { Preferences } from './Preferences/Preferences'
import { download, streamToArrayBuffer } from '../../src/download'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { I18n } from '../shared/I18n/I18n'
import { i18n, I18n } from '../shared/I18n/I18n'
import { useFactories } from '../contexts/FactoryProvider'
import { GraphIcon } from '../icons/GraphIcon'
import { useIntl } from 'react-intl'
export const Home: FC = () => {
const intl = useIntl()
const { query } = useRouter()
const { factories } = useFactories()
const { groups, addGroup, doNotSuggest, ignoredFactories, setIgnoredFactories, store, load } =
useGroups()
const [newGroupValue, setNewGroupValue] = useState('New group')
const preferencesRef = useRef<ElementRef<typeof Preferences>>(null)
const { groups, doNotSuggest, ignoredFactories, setIgnoredFactories, store, load } = useGroups()
const inputRef = useRef<HTMLInputElement>(null)
const [missingExport, missingMall] = useMemo<[EnrichedEntity[], EnrichedEntity[]]>(() => {
@@ -44,7 +46,7 @@ export const Home: FC = () => {
download('factorio-microservices.bin', store())
}}
>
Store
<I18n id={'page.home.pref.download'} />
</button>
<input
type={'file'}
@@ -61,8 +63,13 @@ export const Home: FC = () => {
}
}}
/>
<Link href={{ pathname: '/visualize', query }}>Visualize</Link>
<Preferences />
<Link href={{ pathname: '/visualize', query }}>
<a>
<I18n id={'page.home.pref.visualize'} />
<GraphIcon />
</a>
</Link>
<Preferences ref={preferencesRef} />
<fieldset>
<legend>
<I18n id={'page.home.group.missing.export.title'} />
@@ -76,17 +83,14 @@ export const Home: FC = () => {
key={missing.href}
value={missing}
onClick={() => {
addGroup(newGroupValue !== 'New group' ? newGroupValue : missing.name, [
missing.href
])
setNewGroupValue('New group')
preferencesRef.current?.addGroup(missing.name, [missing.href])
}}
onContextMenu={event => {
event.preventDefault()
setIgnoredFactories([...ignoredFactories, missing.href])
}}
leftClickText={'Create a new group with this name and item as exported factory'}
rightClickText={'Exclude this recipe from suggestions'}
leftClickText={i18n(intl, 'page.home.tooltip.action.add_to_new_export')}
rightClickText={i18n(intl, 'page.home.tooltip.action.exclude_suggestion')}
/>
))}
</div>
@@ -104,19 +108,14 @@ export const Home: FC = () => {
key={missing.href}
value={missing}
onClick={() => {
addGroup(
newGroupValue !== 'New group' ? newGroupValue : missing.name,
[],
[missing.href]
)
setNewGroupValue('New group')
preferencesRef.current?.addGroup(missing.name, undefined, [missing.href])
}}
onContextMenu={event => {
event.preventDefault()
setIgnoredFactories([...ignoredFactories, missing.href])
}}
leftClickText={'Create a new group with this name and item as mall factory'}
rightClickText={'Exclude this recipe from suggestions'}
leftClickText={i18n(intl, 'page.home.tooltip.action.add_to_new_mall')}
rightClickText={i18n(intl, 'page.home.tooltip.action.exclude_suggestion')}
/>
))}
</div>

View File

@@ -1,16 +1,28 @@
import { FC, useState } from 'react'
import { forwardRef, ForwardRefRenderFunction, useImperativeHandle, useState } from 'react'
import { FactorySelect } from '../FactorySelect/FactorySelect'
import { useGroups } from '../../contexts/GroupProvider'
import { i18n, I18n } from '../../shared/I18n/I18n'
import { useIntl } from 'react-intl'
export const Preferences: FC = () => {
interface Handle {
addGroup(preferredName: string, exported?: string[], mall?: string[]): boolean
}
const PreferencesBase: ForwardRefRenderFunction<Handle> = (_, forwardedRef) => {
const intl = useIntl()
const DEFAULT_NAME = i18n(intl, 'page.home.group.add.default_group_name')
useImperativeHandle(forwardedRef, () => ({
addGroup(preferredName: string, exported?: string[], mall?: string[]) {
const name = newGroupValue !== DEFAULT_NAME ? newGroupValue : preferredName
const result = addGroup(name, exported, mall)
result && setNewGroupValue(DEFAULT_NAME)
return result
}
}))
const { addGroup, baseFactories, setBaseFactories, ignoredFactories, setIgnoredFactories } =
useGroups()
const [newGroupValue, setNewGroupValue] = useState(
i18n(intl, 'page.home.group.add.default_group_name')
)
const [newGroupValue, setNewGroupValue] = useState(DEFAULT_NAME)
return (
<>
<fieldset>
@@ -49,7 +61,7 @@ export const Preferences: FC = () => {
disabled={!newGroupValue}
onClick={() => {
addGroup(newGroupValue)
setNewGroupValue('New group')
setNewGroupValue(DEFAULT_NAME)
}}
>
<I18n id={'page.home.group.add.button_text'} values={{ name: newGroupValue }} />
@@ -58,3 +70,5 @@ export const Preferences: FC = () => {
</>
)
}
export const Preferences = forwardRef(PreferencesBase)

View File

@@ -0,0 +1,24 @@
import { FC } from 'react'
import styles from './Icon.module.css'
import cx from 'classnames'
interface Props {
className?: string
}
export const GraphIcon: FC<Props> = ({ className }) => {
return (
<svg
version='1.1'
viewBox='0 0 50 50'
xmlSpace='preserve'
xmlns='http://www.w3.org/2000/svg'
xmlnsXlink='http://www.w3.org/1999/xlink'
className={cx(styles.icon, className)}
>
<g id='Layer_1'>
<path d='M13,37H8V26h16v11h-5v12h12V37h-5V26h16v11h-5v12h12V37h-5V24H26V13h7V1H17v12h7v11H6v13H1v12h12V37z M29,47h-8v-8h8V47z M47,47h-8v-8h8V47z M19,3h12v8H19V3z M11,47H3v-8h8V47z' />
</g>
</svg>
)
}

View File

@@ -0,0 +1,11 @@
.icon {
height: 1em;
padding-inline: 0.5ch;
transform: translateY(0.1em);
}
@media (prefers-color-scheme: dark) {
.icon {
filter: invert(100%);
}
}

View File

@@ -1,4 +1,6 @@
import { FC } from 'react'
import styles from './Icon.module.css'
import cx from 'classnames'
interface Props {
className?: string
@@ -14,7 +16,7 @@ export const LeftClickIcon: FC<Props> = ({ className, classBody, classClick }) =
x='0px'
y='0px'
viewBox='0 0 100 100'
className={className}
className={cx(styles.icon, className)}
>
<path
className={classBody}

View File

@@ -7,6 +7,8 @@ import { EntityIcon } from '../../home/EntityIcon/EntityIcon'
import { GraphNode } from '../../../src/graph-untangle/types'
import { fixedEncodeURIComponent } from '../../../src/utils'
import { useRouter } from 'next/router'
import { GraphIcon } from '../../icons/GraphIcon'
import { I18n } from '../../shared/I18n/I18n'
export type OverviewGraphNode = GraphNode<{
icons: (EnrichedEntity | string)[]
@@ -28,7 +30,7 @@ export const NodeOverview: FC<Props> = ({ node, className, ...props }) => {
query
}}
>
👁
<GraphIcon />
</Link>
</span>
{node.name}
@@ -40,7 +42,9 @@ export const NodeOverview: FC<Props> = ({ node, className, ...props }) => {
))}
</div>
) : null}
<h4>Inputs</h4>
<h4>
<I18n id={'page.visualize.imports'} />
</h4>
<div className={styles.small}>
{node.inputs.map(input => (
<EntityIcon key={input} value={input} />
@@ -48,7 +52,9 @@ export const NodeOverview: FC<Props> = ({ node, className, ...props }) => {
</div>
{node.outputs.length ? (
<>
<h4>Outputs</h4>
<h4>
<I18n id={'page.visualize.exports'} />
</h4>
<div className={styles.small}>
{node.outputs.map(input => (
<EntityIcon key={input} value={input} />

View File

@@ -2,24 +2,36 @@
"page.home.head.title": "Factorio Mikroservices",
"page.home.head.meta.description": "Fasse Factorio Fabriken zu Microservices zusammen",
"page.home.title": "Factorio Mikroservices",
"page.home.description": "Auf dieser Seite kannst du alle Einstellungen vornehmen. Gruppiere alle Fabriken zu Microservices zusammen. Ein Microservice ist eine Ansammlung bestimmter Montagemaschinen und anderen Fertigungen, die sich Eingaben (durch Züge) teilen. Optimale Gruppen sollten daher nur wenige Eingaben haben und viele Gegenstände produzieren. \"Exportierte Fabriken\" sind Ausgaben, die z.B. mit Zügen abgeholt, und für andere Services als Eingabe zu Verfügung stehen. \"Mall-Fabriken\" stellen mit Anbieterkisten die Waren zur Abholung durch den Spieler oder Roboter zur Verfügung. Die benötigten Eingabe-und Zwischenfabriken werden automatisch berechnet.",
"page.home.description": "Auf dieser Seite kannst du alle Einstellungen vornehmen. Gruppiere alle Fabriken zu Microservices zusammen. Ein Microservice ist eine Ansammlung bestimmter Montagemaschinen und anderen Fertigungen, die sich Eingaben (durch Züge) teilen. Optimale Gruppen sollten daher nur wenige Eingaben haben und viele Gegenstände produzieren. \"Exportierte Fabriken\" sind Ausgaben, die z.B. mit Zügen abgeholt, und für andere Services als Eingabe zu Verfügung stehen. \"Einkaufszentren\" stellen mit Anbieterkisten die Waren zur Abholung durch den Spieler oder Roboter zur Verfügung. Die benötigten Eingabe-und Zwischenfabriken werden automatisch berechnet.",
"page.home.pref.download": "Herunterladen",
"page.home.pref.visualize": "Visualisieren",
"page.home.pref.basic.title": "Grundlegende Waren",
"page.home.pref.basic.description": "Grundlegende Waren können nicht in Fabriken hergestellt werden. Es kann sinnvoll sein hier z.B. Eisenplatten hinzuzufügen, wenn jene direkt beim Erz hergestellt werden.",
"page.home.pref.ignored.title": "Ignorierte Waren",
"page.home.pref.ignored.description": "Waren, die in in der Mall hergestellt werden sollen (z.B. Befeuerter Greifarm, weil es nicht benötigt wird) und auch nicht zwischen den Mikroservices exportiert werden sollen (z.B. Zahnräder, weil die bei Bedarf in der Fabrik selbst als Zwischenprodukt hergestellt wird).",
"page.home.pref.ignored.description": "Waren, die im Einkaufszentrum hergestellt werden sollen (z.B. Befeuerter Greifarm, weil es nicht benötigt wird) und auch nicht zwischen den Mikroservices exportiert werden sollen (z.B. Zahnräder, weil die bei Bedarf in der Fabrik selbst als Zwischenprodukt hergestellt wird).",
"page.home.group.add.title": "Neue Gruppe hinzufügen",
"page.home.group.add.default_group_name": "Neue Gruppe",
"page.home.group.add.button_text": "Gruppe \"{name}\" hinzufügen",
"page.home.group.missing.export.title": "Fehlende Export-Fabriken",
"page.home.group.missing.export.description": "Eine Auflistung aller Waren, die keine grundlegenden oder ignorierten Waren sind, und bei noch keiner Gruppe exportiert werden oder als Mall-Fabrik hinzugefügt wurden. Nur in dieser Liste falls von mindestens 3 anderen Waren verwendet.",
"page.home.group.missing.mall.title": "Fehlende Mall-Fabriken",
"page.home.group.missing.mall.description": "Eine Auflistung aller Waren, die keine grundlegenden oder ignorierten Waren sind, und bei noch keiner Gruppe exportiert werden oder als Mall-Fabrik hinzugefügt wurden. Nur in dieser Liste falls von maximal 2 anderen Waren verwendet.",
"page.home.group.missing.export.description": "Eine Auflistung aller Waren, die keine grundlegenden oder ignorierten Waren sind, und bei noch keiner Gruppe exportiert werden oder als Einkaufszentrum hinzugefügt wurden. Nur in dieser Liste falls von mindestens 3 anderen Waren verwendet.",
"page.home.group.missing.mall.title": "Fehlende Einkaufszentren",
"page.home.group.missing.mall.description": "Eine Auflistung aller Waren, die keine grundlegenden oder ignorierten Waren sind, und bei noch keiner Gruppe exportiert werden oder als Einkaufszentrum hinzugefügt wurden. Nur in dieser Liste falls von maximal 2 anderen Waren verwendet.",
"page.home.group.missing.none": "Alle Fabriken hinzugefügt!",
"page.home.group.item.export": "Exportierte Waren",
"page.home.group.item.mall": "Waren für die Mall",
"page.home.group.item.input": "Angelieferte Waren",
"page.home.group.item.intermediate": "Zwischenprodukte",
"page.home.group.item.suggestion.export": "Empfohlene Exportwaren",
"page.home.group.item.suggestion.mall": "Empfohlene Mall-Fabriken",
"page.home.group.delete.confirmation": "Gruppe unwiderruflich löschen?"
"page.home.group.item.mall": "Waren als Einkaufszentrum",
"page.home.group.item.input": "Angelieferte Waren ({amount})",
"page.home.group.item.intermediate": "Zwischenprodukte ({amount})",
"page.home.group.item.suggestion.export": "Vorgeschlagene Exportwaren",
"page.home.group.item.suggestion.mall": "Vorgeschlagene Einkaufszentren",
"page.home.group.delete.confirmation": "Gruppe unwiderruflich löschen?",
"page.home.tooltip.recipe": "Rezept",
"page.home.tooltip.used_by": "Verwendet in",
"page.home.tooltip.actions": "Aktionen",
"page.home.tooltip.action.exclude_suggestion": "Diese Ware von Vorschlägen ausschließen",
"page.home.tooltip.action.add_to_new_mall": "Erstelle eine neue Gruppe mit diesem Namen und dieser Ware als Einkaufszentrum",
"page.home.tooltip.action.add_to_new_export": "Erstelle eine neue Gruppe mit diesem Namen und gut als exportierte Fabrik",
"page.home.tooltip.action.add_to_export": "Ware zu exportierten Fabriken hinzufügen",
"page.home.tooltip.action.add_to_mall": "Ware als Einkaufszentrum hinzufügen",
"page.visualize.imports": "Importe",
"page.visualize.exports": "Exporte"
}

View File

@@ -3,6 +3,8 @@
"page.home.head.meta.description": "Group Factorio factories together into microservices",
"page.home.title": "Factorio Microservices",
"page.home.description": "On this page you can make all settings. Group all factories into microservices. A microservice is a collection of certain assembly machines and other fabrications that share inputs (through trains). Optimal groups should therefore have few inputs and produce many items. \"Exported factories\" are outputs that are picked up by trains, for example, and available to other services as inputs. \"Mall factories\" use vendor crates to make goods available for pickup by the player or robot. The required input and intermediate factories are calculated automatically.",
"page.home.pref.download": "Download",
"page.home.pref.visualize": "Visualize",
"page.home.pref.basic.title": "Basic goods",
"page.home.pref.basic.description": "Basic goods cannot be produced in factories. It may make sense to add iron plates here, for example, if they are produced directly at the ore.",
"page.home.pref.ignored.title": "Ignored goods",
@@ -17,9 +19,19 @@
"page.home.group.missing.none": "All factories added!",
"page.home.group.item.export": "Exported goods",
"page.home.group.item.mall": "Mall goods",
"page.home.group.item.input": "Input goods",
"page.home.group.item.intermediate": "Intermediate factories",
"page.home.group.item.input": "Input goods ({amount})",
"page.home.group.item.intermediate": "Intermediate factories ({amount})",
"page.home.group.item.suggestion.export": "Suggested export goods",
"page.home.group.item.suggestion.mall": "Suggested mall goods",
"page.home.group.delete.confirmation": "Delete group permanently?"
"page.home.group.delete.confirmation": "Delete group permanently?",
"page.home.tooltip.recipe": "Recipe",
"page.home.tooltip.used_by": "Used by",
"page.home.tooltip.actions": "Actions",
"page.home.tooltip.action.exclude_suggestion": "Exclude this good from suggestions",
"page.home.tooltip.action.add_to_new_mall": "Create a new group with this name and good as mall factory",
"page.home.tooltip.action.add_to_new_export": "Create a new group with this name and good as exported factory",
"page.home.tooltip.action.add_to_export": "Add good to exported factories",
"page.home.tooltip.action.add_to_mall": "Add good to mall factories",
"page.visualize.imports": "Imports",
"page.visualize.exports": "Exports"
}

View File

@@ -6,8 +6,7 @@
"jest.config.js",
"next.config.js",
"src/backend-custom-server/index",
"scripts/*",
"res/**/*.json"
"scripts/*"
],
"exclude": ["dist", ".next", "out", "node_modules", "cypress"]
"exclude": ["dist", ".next", "out", "node_modules", "cypress", "*.json"]
}