diff --git a/build.ts b/build.ts index 9dd903416..74a6b3d08 100755 --- a/build.ts +++ b/build.ts @@ -1,6 +1,7 @@ import * as packageJson from './package.json'; import * as path from 'path'; import { promises as fs } from 'fs'; +import { execSync } from 'child_process'; import * as esbuild from 'esbuild'; import axios, { AxiosResponse } from 'axios'; @@ -200,6 +201,8 @@ const Plugin = { }, }; +execSync('ts-node scripts/gen-lang-registry.ts', { stdio: 'inherit' }); + // TODO: Switch `yarn serve` to use `esbuild.serve` which prevents stale // responses and minimizes FS writes. void esbuild.build({ diff --git a/scripts/gen-lang-registry.ts b/scripts/gen-lang-registry.ts new file mode 100644 index 000000000..73896912f --- /dev/null +++ b/scripts/gen-lang-registry.ts @@ -0,0 +1,29 @@ +import fs from 'fs'; +import path from 'path'; + +const LANGS_DIR = path.resolve(__dirname, '../src/components/dictionary/langs'); +const INDEX_FILE = path.resolve(__dirname, '../src/components/dictionary/index.ts'); + +async function generateRegistry() { + const files = fs.readdirSync(LANGS_DIR).filter((f) => f.endsWith('.ts')); + + const imports = files + .map((file) => { + const name = path.basename(file, '.ts'); + return `import { ${name}Plugin } from './langs/${name}';`; + }) + .join('\n'); + + const registry = files + .map((file) => { + const name = path.basename(file, '.ts'); + return ` ${JSON.stringify(name)}: ${name}Plugin,`; + }) + .join('\n'); + + const content = `import Dictionary from './Dictionary';\n${imports}\nimport { LanguagePlugin } from './types';\n\nexport const languageRegistry: Record = {\n${registry}\n};\n\nexport default Dictionary;\n`; + + fs.writeFileSync(INDEX_FILE, content); +} + +generateRegistry(); diff --git a/src/App.tsx b/src/App.tsx index 8780ccb22..386c920bc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,6 +14,7 @@ import { langDirection, toAlpha2Code } from './util/languages'; import { Mode } from './types'; import Analyzer from './components/Analyzer'; +import Dictionary from './components/dictionary'; import { Path as DocTranslationPath } from './components/translator/DocTranslationForm'; import Footer from './components/footer'; import Generator from './components/Generator'; @@ -31,6 +32,7 @@ const Interfaces = { [Mode.Analysis]: Analyzer, [Mode.Generation]: Generator, [Mode.Sandbox]: Sandbox, + [Mode.Dictionary]: Dictionary, // dict } as Record>; const App = ({ setLocale }: { setLocale: React.Dispatch> }): React.ReactElement => { diff --git a/src/components/dictionary/CombinedWord.css b/src/components/dictionary/CombinedWord.css new file mode 100644 index 000000000..786a964ca --- /dev/null +++ b/src/components/dictionary/CombinedWord.css @@ -0,0 +1,18 @@ +.roman-numeral { + margin-left: 0.5rem; + font-style: normal; + font-weight: 600; + font-size: 1rem; +} + +.pos-tag { + margin-left: 0.5rem; + color: #6c757d; + font-size: 0.875rem; +} + +.entry-divider { + border: none; + border-top: 1px solid #dee2e6; + margin: 1rem 0; +} diff --git a/src/components/dictionary/CombinedWord.tsx b/src/components/dictionary/CombinedWord.tsx new file mode 100644 index 000000000..3cdea26f8 --- /dev/null +++ b/src/components/dictionary/CombinedWord.tsx @@ -0,0 +1,228 @@ +import React, { useState, useEffect, useContext } from 'react'; +import './Word.css'; +import './CombinedWord.css'; +import Spinner from 'react-bootstrap/Spinner'; +import Dropdown from 'react-bootstrap/Dropdown'; +import Paradigm from './Paradigm'; +import { APyContext } from '../../context'; +import { useLocalization, useLocalizationPOS } from '../../util/localization'; +import { getPosTag } from '../../util/posLocalization'; +import { languageRegistry } from './index'; + +export interface Entry { + head: string; + defs: string[]; + similarTo?: string; + extraTags?: string[]; +} + +const toRoman = (n: number): string => { + const lookup: Record = { + 1: 'I', + 2: 'II', + 3: 'III', + 4: 'IV', + 5: 'V', + 6: 'VI', + 7: 'VII', + 8: 'VIII', + 9: 'IX', + 10: 'X', + }; + return lookup[n] || n.toString(); +}; + +interface EntryBlockProps { + surface: string; + entry: Entry; + lang: string; + index: number; + total: number; + onDefinitionClick: (def: string) => void; + searchWord: string; +} + +const EntryBlock: React.FC = ({ + surface, + entry, + lang, + index, + total, + onDefinitionClick, + searchWord, +}) => { + const apyFetch = useContext(APyContext); + const { t } = useLocalization(); + const { locale } = useLocalizationPOS(); + + const plugin = languageRegistry[lang] || null; + const availableModes = plugin?.getAvailableModes ? plugin.getAvailableModes(locale) : []; + + const rawBlocks = plugin + ? plugin.addParadigms({ head: entry.head, mode: availableModes[0] || '', locale, t, apyFetch }) + : []; + const hasParadigms = Array.isArray(rawBlocks) && rawBlocks.length > 0; + + const [expanded, setExpanded] = useState(false); + const [loadingParadigm, setLoadingParadigm] = useState(false); + const [mode, setMode] = useState(availableModes[0] || ''); + + useEffect(() => { + if (availableModes.length && !availableModes.includes(mode)) { + setMode(availableModes[0]); + } + }, [availableModes, mode, locale]); + + const tags: string[] = []; + let m: RegExpExecArray | null; + const re = /<([^>]+)>/g; + while ((m = re.exec(entry.head))) tags.push(m[1]); + const displayTag = tags.length ? getPosTag(locale, tags.join('.')) : null; + + const showRoman = total > 1; + const roman = showRoman ? toRoman(index + 1) : ''; + + const cleanSurface = surface; + const cleanDefs = entry.defs.map((d) => d.replace(/<[^>]+>/g, '')); + + const cleanedSearch = searchWord.replace(/<[^>]+>/g, ''); + const nonExact = cleanSurface !== cleanedSearch; + + const extraTagsString = entry.extraTags && entry.extraTags.length ? entry.extraTags.join('') : ''; + const extraTokens = Array.from(extraTagsString.matchAll(/<([^>]+)>/g)).map((mm) => mm[1]); + + const segmentMorphLabels = (tokens: string[]): string | null => { + let i = 0; + const labels: string[] = []; + while (i < tokens.length) { + let foundLabel: string | null = null; + let foundLen = 0; + for (let j = tokens.length; j > i; j--) { + const key = tokens.slice(i, j).join('.'); + const lbl = getPosTag(locale, key); + if (lbl && lbl !== key) { + foundLabel = lbl; + foundLen = j - i; + break; + } + } + if (foundLabel) { + labels.push(foundLabel); + i += foundLen; + } else { + i += 1; + } + } + return labels.length ? labels.join(' ') : null; + }; + + const morphLabel = segmentMorphLabels(extraTokens); + const extraDisplay = morphLabel || extraTagsString; + + const handleToggle = () => { + if (!expanded) { + setExpanded(true); + setLoadingParadigm(true); + } else { + setExpanded(false); + } + }; + + return ( +
+
+ + {cleanSurface} + {showRoman && {roman}} + {displayTag && ({displayTag})} + +
+
    + {cleanDefs.map((rawDef, i) => { + const def = rawDef; + return ( +
  1. onDefinitionClick(def)}> + {def} +
  2. + ); + })} +
+ {entry.similarTo && ( +
+ + {t('Similar_To')} {entry.similarTo} + +
+ )} + {nonExact && extraTagsString && ( +
+ {extraDisplay}: {cleanedSearch} +
+ )} + {hasParadigms && ( +
+ + {expanded && availableModes.length > 1 && ( + typeof k === 'string' && setMode(k)}> + + {mode} + + + {availableModes.map((mk) => ( + + {mk} + + ))} + + + )} +
+ )} + {hasParadigms && expanded && ( +
+ setLoadingParadigm(false)} /> +
+ )} +
+ ); +}; + +interface CombinedWordProps { + surface: string; + entries: Entry[]; + lang: string; + onDefinitionClick: (def: string) => void; + searchWord: string; +} + +const CombinedWord: React.FC = ({ surface, entries, lang, onDefinitionClick, searchWord }) => ( +
+ {entries.map((e, idx) => ( + + + {idx < entries.length - 1 &&
} + + ))} +
+); + +export default CombinedWord; diff --git a/src/components/dictionary/Dictionary.tsx b/src/components/dictionary/Dictionary.tsx new file mode 100644 index 000000000..cd2f2e148 --- /dev/null +++ b/src/components/dictionary/Dictionary.tsx @@ -0,0 +1,862 @@ +import * as React from 'react'; +import Form from 'react-bootstrap/Form'; +import Button from 'react-bootstrap/Button'; +import Spinner from 'react-bootstrap/Spinner'; +import { CancelTokenSource } from 'axios'; +import { isPair, Pairs } from '../translator'; +import LanguageSelector from '../dictionary/LanguageSelector'; +import { toAlpha3Code } from '../../util/languages'; +import useLocalStorage from '../../util/useLocalStorage'; +import { getUrlParam } from '../../util/url'; +import { APyContext } from '../../context'; +import CombinedWord, { Entry } from './CombinedWord'; +import { useLocalization } from '../../util/localization'; +import { useHistory } from 'react-router-dom'; + +const recentLangsCount = 3; + +const defaultSrcLang = (pairs: Pairs): string => { + const keys = Object.keys(pairs); + return keys.length ? keys[0] : ''; +}; + +type WithSrcLangsProps = { + srcLang: string; + setSrcLang: (lang: string) => void; + recentSrcLangs: string[]; + setRecentSrcLangs: (langs: string[]) => void; + detectedLang: string | null; + setDetectedLang: (lang: string | null) => void; +}; + +const WithSrcLang = ({ + pairs, + urlSrcLang, + children, +}: { + pairs: Pairs; + urlSrcLang: string | null; + children: (props: WithSrcLangsProps) => React.ReactElement; +}) => { + const opts: any = { validateValue: (l: string) => l in pairs }; + if (urlSrcLang) opts.overrideValue = urlSrcLang; + const [srcLang, rawSetSrcLang] = useLocalStorage('dictSrcLang', () => defaultSrcLang(pairs), opts); + const [recentSrcLangs, rawSetRecentSrcLangs] = useLocalStorage('dictRecentSrcLangs', () => [srcLang], { + validateValue: (ls) => Array.isArray(ls) && ls.every((l) => l in pairs), + }); + const setSrcLang = React.useCallback( + (lang: string) => { + rawSetSrcLang(lang); + rawSetRecentSrcLangs((prev) => Array.from(new Set([lang, ...prev])).slice(0, recentLangsCount)); + }, + [rawSetSrcLang, rawSetRecentSrcLangs], + ); + const [detectedLang, setDetectedLang] = React.useState(null); + const setDetectedLangCb = React.useCallback( + (lang: string | null) => { + setDetectedLang(lang); + if (lang) setSrcLang(lang); + }, + [setSrcLang], + ); + return children({ + srcLang, + setSrcLang, + recentSrcLangs, + setRecentSrcLangs: rawSetRecentSrcLangs, + detectedLang, + setDetectedLang: setDetectedLangCb, + }); +}; + +type WithTgtLangsProps = { + tgtLang: string; + setTgtLang: (lang: string) => void; + recentTgtLangs: string[]; +}; + +const WithTgtLang = ({ + pairs, + srcLang, + urlTgtLang, + children, +}: { + pairs: Pairs; + srcLang: string; + urlTgtLang: string | null; + children: (props: WithTgtLangsProps) => React.ReactElement; +}) => { + const opts: any = { validateValue: (l: string) => isPair(pairs, srcLang, l) }; + if (urlTgtLang) opts.overrideValue = urlTgtLang; + const [tgtLang, rawSetTgtLang] = useLocalStorage( + 'dictTgtLang', + () => { + const set = pairs[srcLang]; + return set ? Array.from(set)[0] : ''; + }, + opts, + ); + const [recentTgtLangs, rawSetRecentTgtLangs] = useLocalStorage('dictRecentTgtLangs', () => [tgtLang], { + validateValue: (ls) => Array.isArray(ls) && ls.every((l) => isPair(pairs, srcLang, l)), + }); + const setTgtLang = React.useCallback( + (lang: string) => { + rawSetTgtLang(lang); + rawSetRecentTgtLangs((prev) => Array.from(new Set([lang, ...prev])).slice(0, recentLangsCount)); + }, + [rawSetTgtLang, rawSetRecentTgtLangs], + ); + React.useEffect(() => { + if (!isPair(pairs, srcLang, tgtLang)) { + const fallback = recentTgtLangs.find((l) => isPair(pairs, srcLang, l)); + const newTgt = fallback || (pairs[srcLang] ? Array.from(pairs[srcLang])[0] : ''); + if (newTgt && newTgt !== tgtLang) setTgtLang(newTgt); + } + }, [pairs, srcLang, tgtLang, recentTgtLangs, setTgtLang]); + return children({ tgtLang, setTgtLang, recentTgtLangs }); +}; + +const stripTagsAndHashes = (s: string) => + s + .replace(/<[^>]+>/g, '') + .replace(/#/g, '') + .replace(/\s{2,}/g, ' ') + .trim(); + +const stripTagsLower = (s: string) => stripTagsAndHashes(s).toLowerCase(); + +const dedupeEmbeddingEntries = (entries: Entry[]): Entry[] => { + const byKey = new Map; extraTags?: string[] }>(); + for (const e of entries) { + const headKey = stripTagsLower(e.head); + for (const d of e.defs) { + const defKey = stripTagsLower(d); + const key = `${headKey}|${defKey}`; + const existing = byKey.get(key); + if (!existing) { + byKey.set(key, { + head: e.head, + def: d, + sims: new Set(e.similarTo ? [e.similarTo] : []), + extraTags: e.extraTags, + }); + } else { + if (e.similarTo) existing.sims.add(e.similarTo); + if (e.extraTags) { + existing.extraTags = Array.from(new Set([...(existing.extraTags || []), ...e.extraTags])); + } + } + } + } + const out: Entry[] = []; + byKey.forEach(({ head, def, sims, extraTags }) => { + const simList = Array.from(sims); + const similarTo = simList.length ? simList.join(', ') : undefined; + out.push({ + head, + defs: [def], + ...(similarTo ? { similarTo } : {}), + ...(extraTags && extraTags.length ? { extraTags } : {}), + }); + }); + return out; +}; + +const Dictionary: React.FC = () => { + const { t } = useLocalization(); + const history = useHistory(); + const originalApyFetch = React.useContext(APyContext); + + const apyFetch = React.useMemo(() => { + type Pending = { + lang: string; + q: string; + resolve: (v: any) => void; + reject: (e: any) => void; + canceled: boolean; + source: CancelTokenSource; + }; + const queuesRef = { current: new Map() } as { current: Map }; + const timerRef = { current: null as number | null }; + + const flush = () => { + queuesRef.current.forEach((list, lang) => { + const active = list.filter((p) => !p.canceled); + queuesRef.current.set(lang, []); + let idx = 0; + while (idx < active.length) { + const batch = active.slice(idx, idx + 10); + idx += 10; + if (!batch.length) continue; + const q = batch.map((b) => b.q).join(' '); + const [, req] = originalApyFetch('generate', { lang, q }); + req + .then((resp: any) => { + const raw = resp?.data?.responseData ?? resp?.data ?? []; + const arr = Array.isArray(raw) ? raw : []; + const dataIsArray = Array.isArray(resp?.data); + const hasResponseDataArray = Array.isArray(resp?.data?.responseData); + batch.forEach((p, i) => { + if (p.canceled) return; + const pair = arr[i]; + let perItem: any; + if (dataIsArray) { + perItem = { data: pair !== undefined ? [pair] : [] }; + } else if (hasResponseDataArray) { + perItem = { data: { responseData: pair !== undefined ? [pair] : [] } }; + } else { + perItem = { data: pair !== undefined ? [pair] : [] }; + } + p.resolve(perItem); + }); + }) + .catch((err: any) => { + batch.forEach((p) => { + if (!p.canceled) p.reject(err); + }); + }); + } + }); + }; + + const scheduleFlush = () => { + if (timerRef.current == null) { + timerRef.current = window.setTimeout(() => { + timerRef.current = null; + flush(); + }, 0); + } + }; + + const wrapped = (endpoint: string, params: Record) => { + if (endpoint !== 'generate') return originalApyFetch(endpoint, params); + const { lang, q } = params || {}; + let res: (v: any) => void = () => {}; + let rej: (e: any) => void = () => {}; + const promise = new Promise((resolve, reject) => { + res = resolve; + rej = reject; + }); + const pending: Partial = { lang, q, resolve: res, reject: rej, canceled: false } as any; + const source: CancelTokenSource = { cancel: () => ((pending as Pending).canceled = true) } as any; + (pending as Pending).source = source; + const list = queuesRef.current.get(lang) || []; + list.push(pending as Pending); + queuesRef.current.set(lang, list); + scheduleFlush(); + return [source, promise] as [CancelTokenSource, Promise]; + }; + + return wrapped; + }, [originalApyFetch]); + + const [pairs, setPairs] = React.useState({}); + const [loadingPairs, setLoadingPairs] = React.useState(true); + const fetchRef = React.useRef(null); + const embeddingModesPromiseRef = React.useRef> | null>(null); + + const loadEmbeddingModes = React.useCallback(async (): Promise> => { + if (!embeddingModesPromiseRef.current) { + embeddingModesPromiseRef.current = (async () => { + try { + const [, listReq] = apyFetch('list', { q: 'embeddings' }); + const listRes = await listReq; + const respData = listRes.data.responseData; + const modes: string[] = []; + if (Array.isArray(respData)) { + respData.forEach((item) => { + if (typeof item === 'string' && item.includes('|')) { + modes.push(item); + } else if (item && typeof item === 'object') { + const s = (item as any).sourceLanguage; + const tLang = (item as any).targetLanguage; + if (typeof s === 'string' && typeof tLang === 'string') { + modes.push(`${s}|${tLang}`); + } + } + }); + } else if (respData && typeof respData === 'object') { + const maybe = (respData as any).embeddingModes ?? (respData as any).availableEmbeddings; + if (Array.isArray(maybe)) { + maybe.forEach((item) => { + if (typeof item === 'string' && item.includes('|')) { + modes.push(item); + } else if (item && typeof item === 'object') { + const s = (item as any).sourceLanguage; + const tLang = (item as any).targetLanguage; + if (typeof s === 'string' && typeof tLang === 'string') { + modes.push(`${s}|${tLang}`); + } + } + }); + } + } + return new Set(modes); + } catch { + return new Set(); + } + })(); + } + return embeddingModesPromiseRef.current!; + }, [apyFetch]); + + const chooseEmbeddingMode = React.useCallback( + async (src: string, tgt: string): Promise => { + const modesSet = await loadEmbeddingModes(); + const forward = `${src}|${tgt}`; + const reverse = `${tgt}|${src}`; + if (modesSet.has(forward)) return forward; + if (modesSet.has(reverse)) return reverse; + return null; + }, + [loadEmbeddingModes], + ); + + React.useEffect(() => { + fetchRef.current?.cancel(); + const [ref, request] = apyFetch('list', { q: 'billookup' }); + fetchRef.current = ref; + setLoadingPairs(true); + request + .then((resp) => { + const arr: Array<{ sourceLanguage: string; targetLanguage: string }> = resp.data.responseData || []; + const dict: Pairs = {}; + arr.forEach(({ sourceLanguage: s, targetLanguage: t }) => { + if (!dict[s]) dict[s] = new Set(); + dict[s].add(t); + }); + setPairs(dict); + }) + .catch((err) => console.error('Error loading pairs:', err)) + .finally(() => { + setLoadingPairs(false); + fetchRef.current = null; + }); + return () => fetchRef.current?.cancel(); + }, [apyFetch]); + + React.useEffect(() => { + const handleLocationChange = () => { + window.location.reload(); + }; + + const unlisten = history.listen(handleLocationChange); + return unlisten; + }, [history]); + + if (loadingPairs) { + return ( +
+ +
+ ); + } + + const urlPair = getUrlParam(history.location.search, 'langpair'); + const initialQ = getUrlParam(history.location.search, 'q') || ''; + let urlSrc: string | null = null; + let urlTgt: string | null = null; + if (urlPair) { + const [s, t] = urlPair.split('-', 2).map(toAlpha3Code); + if (s && t && isPair(pairs, s, t)) { + urlSrc = s; + urlTgt = t; + } + } + + return ( + + + {({ srcLang, setSrcLang, recentSrcLangs, setRecentSrcLangs, detectedLang, setDetectedLang }) => ( + + {({ tgtLang, setTgtLang, recentTgtLangs }) => { + const [inputWord, setInputWord] = React.useState(initialQ); + const [activeWord, setActiveWord] = React.useState(''); + const [loading, setLoading] = React.useState(false); + const [searched, setSearched] = React.useState(false); + const searchRef = React.useRef(null); + const [results, setResults] = React.useState([]); + const [reverseResults, setReverseResults] = React.useState([]); + const [embeddingResults, setEmbeddingResults] = React.useState([]); + const bootstrappedFromUrlRef = React.useRef(false); + + React.useEffect(() => { + setResults([]); + setReverseResults([]); + setEmbeddingResults([]); + setSearched(false); + }, [srcLang, tgtLang]); + + React.useEffect(() => { + if (!bootstrappedFromUrlRef.current && initialQ) return; + const url = new URL(window.location.href); + const trimmed = inputWord.trim(); + if (trimmed) { + url.searchParams.set('q', trimmed); + } else if (bootstrappedFromUrlRef.current) { + url.searchParams.delete('q'); + } + url.searchParams.set('langpair', `${srcLang}-${tgtLang}`); + url.hash = ''; + const next = url.toString(); + if (next !== window.location.href) { + window.history.replaceState(null, '', next); + } + }, [inputWord, srcLang, tgtLang, initialQ]); + + const handleSearch = React.useCallback( + async (wordOverride?: string, srcOverride: string = srcLang, tgtOverride: string = tgtLang) => { + const rawWord = (wordOverride ?? inputWord).trim(); + if (!rawWord) return; + + setActiveWord(rawWord); + setSearched(true); + searchRef.current?.cancel(); + setLoading(true); + setResults([]); + setReverseResults([]); + setEmbeddingResults([]); + + const [, reqFwd] = apyFetch('billookup', { + q: `${rawWord}<*>`, + langpair: `${srcOverride}|${tgtOverride}`, + }); + const [, reqRev] = apyFetch('billookup', { + q: `${rawWord}<*>`, + langpair: `${tgtOverride}|${srcOverride}`, + }); + + let revParsed: Entry[] = []; + + const parse = (resp: any): Entry[] => { + const raw = resp.data.responseData?.lookupResults ?? resp.data.responseData?.searchResults ?? []; + return (raw as Array>).flatMap((o) => { + const extraTagsArr: string[] = Array.isArray(o['extra-tags']) ? o['extra-tags'] : []; + return Object.entries(o) + .filter(([head]) => head !== 'extra-tags') + .map( + ([head, defs]) => + ({ + head, + defs, + extraTags: extraTagsArr, + } as Entry), + ); + }); + }; + + try { + const [respFwd, respRev] = await Promise.all([reqFwd, reqRev]); + const fwdParsed = parse(respFwd); + setResults(fwdParsed); + + const reverseRaw = parse(respRev); + revParsed = reverseRaw.flatMap(({ head, defs }) => + defs.map((d) => ({ head: d.replace(/^\s*\d+\.\s*/, ''), defs: [head] } as Entry)), + ); + const uniqueHeads = Array.from(new Set(revParsed.map((r) => r.head))); + const headResponses = await Promise.all( + uniqueHeads.map((h) => + apyFetch('bilsearch', { q: h, langpair: `${srcOverride}|${tgtOverride}` })[1].then(parse), + ), + ); + const enriched: Record = {}; + headResponses.forEach((arr, i) => { + enriched[uniqueHeads[i]] = Array.from( + new Set(arr.flatMap((item) => item.defs.map((d) => stripTagsAndHashes(d))).filter(Boolean)), + ); + }); + setReverseResults(uniqueHeads.map((h) => ({ head: h, defs: enriched[h] } as Entry))); + + const cleanedWord = stripTagsLower(rawWord); + const exactForward = fwdParsed.find((item) => stripTagsLower(item.head) === cleanedWord); + const exactReverse = reverseRaw.find((item) => stripTagsLower(item.head) === cleanedWord); + + let headerTerm: string | null = null; + let translations: string[] = []; + let headLang: string = srcOverride; + let translationLang: string = tgtOverride; + let exactMatchFound = false; + + if (exactForward) { + headerTerm = stripTagsAndHashes(exactForward.head); + translations = exactForward.defs.map((d) => stripTagsAndHashes(d)); + headLang = srcOverride; + translationLang = tgtOverride; + exactMatchFound = true; + } else if (exactReverse) { + headerTerm = stripTagsAndHashes(exactReverse.head); + translations = exactReverse.defs.map((d) => stripTagsAndHashes(d)); + headLang = tgtOverride; + translationLang = srcOverride; + exactMatchFound = true; + } + + if (!exactMatchFound) { + const modesSet = await loadEmbeddingModes(); + const forwardMode = `${srcOverride}|${tgtOverride}`; + const reverseMode = `${tgtOverride}|${srcOverride}`; + const availableModes: string[] = []; + if (modesSet.has(forwardMode)) availableModes.push(forwardMode); + if (modesSet.has(reverseMode)) availableModes.push(reverseMode); + if (availableModes.length === 0) { + setEmbeddingResults([]); + } else { + type Job = { term: string; embeddingMode: string; termLang: string }; + const jobs: Job[] = availableModes.map((mode) => ({ + term: rawWord, + embeddingMode: mode, + termLang: srcOverride, + })); + const jobResults: Array<{ + term: string; + embeddingMode: string; + sims: string[]; + termLang: string; + }> = []; + await Promise.all( + jobs.map(async (job) => { + const simsSet = new Set(); + const [, embReq] = apyFetch('embeddings', { + q: job.term, + langpair: job.embeddingMode, + }); + try { + const embRes = await embReq; + const sims: string[] = + embRes.data.responseData?.embeddingResults?.flatMap((obj: any) => + Object.values(obj).flat(), + ) || []; + sims.forEach((s) => { + if (!s.startsWith('*')) simsSet.add(s); + }); + } catch {} + jobResults.push({ + term: job.term, + embeddingMode: job.embeddingMode, + sims: Array.from(simsSet), + termLang: job.termLang, + }); + }), + ); + const simsByMode: Record = {}; + jobResults.forEach(({ embeddingMode, sims }) => { + if (!simsByMode[embeddingMode]) simsByMode[embeddingMode] = []; + sims.forEach((s) => { + if (!simsByMode[embeddingMode].includes(s)) simsByMode[embeddingMode].push(s); + }); + }); + const bilsearchParsed: Record> = {}; + await Promise.all( + Object.entries(simsByMode).map(async ([mode, sims]) => { + bilsearchParsed[mode] = {}; + await Promise.all( + sims.map(async (sim) => { + const [, bsReq] = apyFetch('bilsearch', { q: sim, langpair: mode }); + try { + const resp = await bsReq; + const raw = resp.data.responseData?.searchResults ?? []; + const parsed = (raw as Array>).flatMap((o) => + Object.entries(o) + .filter(([head]) => head !== 'extra-tags') + .map( + ([hd, defs]) => + ({ + head: hd, + defs, + extraTags: Array.isArray(o['extra-tags']) ? o['extra-tags'] : [], + } as Entry), + ), + ); + bilsearchParsed[mode][sim] = parsed; + } catch { + bilsearchParsed[mode][sim] = []; + } + }), + ); + }), + ); + const embEntries: Entry[] = []; + jobResults.forEach(({ embeddingMode, sims, term }) => { + const isReverseEmbeddingMode = embeddingMode === `${tgtOverride}|${srcOverride}`; + const displaySimilarTo = term; + sims.forEach((sim) => { + const parsed = bilsearchParsed[embeddingMode]?.[sim] || []; + parsed.forEach(({ head: bilHead, defs }) => { + defs.forEach((def) => { + if (isReverseEmbeddingMode) { + embEntries.push({ + head: def, + defs: [bilHead], + similarTo: displaySimilarTo, + } as Entry); + } else { + embEntries.push({ + head: bilHead, + defs: [def], + similarTo: displaySimilarTo, + } as Entry); + } + }); + }); + }); + }); + setEmbeddingResults(dedupeEmbeddingEntries(embEntries)); + } + } else { + const modesSet = await loadEmbeddingModes(); + const termLang: Record = {}; + if (headerTerm) termLang[headerTerm] = headLang; + translations.forEach((tr) => { + termLang[tr] = translationLang; + }); + type Job = { term: string; termLang: string; embeddingMode: string }; + const jobsMap = new Map(); + const forwardMode = `${srcOverride}|${tgtOverride}`; + const reverseMode = `${tgtOverride}|${srcOverride}`; + if (headerTerm) { + if (termLang[headerTerm] === srcOverride && modesSet.has(forwardMode)) { + const key = `${headerTerm}|${forwardMode}`; + jobsMap.set(key, { + term: headerTerm, + termLang: termLang[headerTerm], + embeddingMode: forwardMode, + }); + } + if (termLang[headerTerm] === tgtOverride && modesSet.has(reverseMode)) { + const key = `${headerTerm}|${reverseMode}`; + jobsMap.set(key, { + term: headerTerm, + termLang: termLang[headerTerm], + embeddingMode: reverseMode, + }); + } + } + translations.forEach((tr) => { + if (termLang[tr] === srcOverride && modesSet.has(forwardMode)) { + const key = `${tr}|${forwardMode}`; + jobsMap.set(key, { term: tr, termLang: termLang[tr], embeddingMode: forwardMode }); + } + if (termLang[tr] === tgtOverride && modesSet.has(reverseMode)) { + const key = `${tr}|${reverseMode}`; + jobsMap.set(key, { term: tr, termLang: termLang[tr], embeddingMode: reverseMode }); + } + }); + const jobs = Array.from(jobsMap.values()); + const jobResults: Array<{ + term: string; + embeddingMode: string; + sims: string[]; + termLang: string; + }> = []; + await Promise.all( + jobs.map(async (job) => { + const simsSet = new Set(); + const [, embReq] = apyFetch('embeddings', { + q: job.term, + langpair: job.embeddingMode, + }); + try { + const embRes = await embReq; + const sims: string[] = + embRes.data.responseData?.embeddingResults?.flatMap((obj: any) => + Object.values(obj).flat(), + ) || []; + sims.forEach((s) => { + if (!s.startsWith('*')) simsSet.add(s); + }); + } catch {} + jobResults.push({ + term: job.term, + embeddingMode: job.embeddingMode, + sims: Array.from(simsSet), + termLang: job.termLang, + }); + }), + ); + const simsByMode: Record = {}; + jobResults.forEach(({ embeddingMode, sims }) => { + if (!simsByMode[embeddingMode]) simsByMode[embeddingMode] = []; + sims.forEach((s) => { + if (!simsByMode[embeddingMode].includes(s)) simsByMode[embeddingMode].push(s); + }); + }); + const bilsearchParsed: Record> = {}; + await Promise.all( + Object.entries(simsByMode).map(async ([mode, sims]) => { + bilsearchParsed[mode] = {}; + await Promise.all( + sims.map(async (sim) => { + const [, bsReq] = apyFetch('bilsearch', { q: sim, langpair: mode }); + try { + const resp = await bsReq; + const raw = resp.data.responseData?.searchResults ?? []; + const parsed = (raw as Array>).flatMap((o) => + Object.entries(o) + .filter(([head]) => head !== 'extra-tags') + .map( + ([hd, defs]) => + ({ + head: hd, + defs, + extraTags: Array.isArray(o['extra-tags']) ? o['extra-tags'] : [], + } as Entry), + ), + ); + bilsearchParsed[mode][sim] = parsed; + } catch { + bilsearchParsed[mode][sim] = []; + } + }), + ); + }), + ); + const embEntries: Entry[] = []; + jobResults.forEach(({ embeddingMode, sims, termLang, term }) => { + const [embedSourceLang] = embeddingMode.split('|'); + const isReverseEmbeddingMode = embeddingMode === `${tgtOverride}|${srcOverride}`; + const getEquivalentInLang = (orig: string, fromLang: string, toLang: string): string => { + if (fromLang === toLang) return orig; + if (headerTerm) { + if (fromLang === headLang && toLang === translationLang) { + return translations[0] || orig; + } + if (fromLang === translationLang && toLang === headLang) { + return headerTerm; + } + } + return orig; + }; + const displaySimilarTo = getEquivalentInLang(term, termLang, embedSourceLang); + sims.forEach((sim) => { + const parsed = bilsearchParsed[embeddingMode]?.[sim] || []; + parsed.forEach(({ head: bilHead, defs }) => { + defs.forEach((def) => { + if (isReverseEmbeddingMode) { + embEntries.push({ + head: def, + defs: [bilHead], + similarTo: displaySimilarTo, + } as Entry); + } else { + embEntries.push({ + head: bilHead, + defs: [def], + similarTo: displaySimilarTo, + } as Entry); + } + }); + }); + }); + }); + setEmbeddingResults(dedupeEmbeddingEntries(embEntries)); + } + } catch { + setReverseResults(revParsed); + } finally { + setLoading(false); + searchRef.current = null; + } + }, + [apyFetch, inputWord, srcLang, tgtLang, loadEmbeddingModes], + ); + + React.useEffect(() => { + if (bootstrappedFromUrlRef.current) return; + if (!initialQ) return; + if (!srcLang || !tgtLang) return; + bootstrappedFromUrlRef.current = true; + setActiveWord(initialQ); + handleSearch(initialQ, srcLang, tgtLang); + }, [initialQ, srcLang, tgtLang, handleSearch]); + + const grouped: Record = React.useMemo(() => { + const all: Entry[] = [...results, ...reverseResults, ...embeddingResults]; + const map: Record = {}; + all.forEach((e) => { + const surface = stripTagsAndHashes(e.head); + if (!map[surface]) map[surface] = []; + map[surface].push({ + head: e.head, + defs: e.defs.map((d) => stripTagsAndHashes(d)), + ...(e.similarTo ? { similarTo: e.similarTo } : {}), + ...(e.extraTags ? { extraTags: e.extraTags } : {}), + } as Entry); + }); + return map; + }, [results, reverseResults, embeddingResults]); + + return ( +
{ + e.preventDefault(); + handleSearch(); + }} + > + handleSearch()} + detectedLang={detectedLang} + setDetectedLang={setDetectedLang} + /> + + setInputWord(e.target.value)} + /> + +
+ +
+
+ {Object.entries(grouped) + .sort(([a], [b]) => { + if (a === activeWord && b !== activeWord) return -1; + if (b === activeWord && a !== activeWord) return 1; + return 0; + }) + .map(([surface, entries]) => ( + { + setInputWord(def); + setActiveWord(def); + setSrcLang(tgtLang); + setTgtLang(srcLang); + handleSearch(def, tgtLang, srcLang); + }} + /> + ))} + {searched && !loading && Object.keys(grouped).length === 0 && ( +
{t('No_results_found')}
+ )} +
+ + ); + }} +
+ )} +
+
+ ); +}; + +export default Dictionary; diff --git a/src/components/dictionary/LanguageSelector.tsx b/src/components/dictionary/LanguageSelector.tsx new file mode 100644 index 000000000..3c7793a21 --- /dev/null +++ b/src/components/dictionary/LanguageSelector.tsx @@ -0,0 +1,445 @@ +import * as React from 'react'; +import Button from 'react-bootstrap/Button'; +import { faExchangeAlt } from '@fortawesome/free-solid-svg-icons'; +import ButtonGroup from 'react-bootstrap/ButtonGroup'; +import Col from 'react-bootstrap/Col'; +import DropdownButton from 'react-bootstrap/DropdownButton'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import Form from 'react-bootstrap/Form'; +import Row from 'react-bootstrap/Row'; +import classNames from 'classnames'; + +import { NamedLangs, Pairs, SrcLangs, TgtLangs, isPair } from '../translator'; +import WithSortedLanguages, { ChildProps } from '../translator/WithSortedLanguages'; +import { isVariant, langDirection } from '../../util/languages'; +import { LocaleContext } from '../../context'; +import { useLocalization } from '../../util/localization'; + +export type Props = { + pairs: Pairs; + + srcLang: string; + setSrcLang: (code: string) => void; + recentSrcLangs: Array; + setRecentSrcLangs: (langs: Array) => void; + + tgtLang: string; + setTgtLang: (code: string) => void; + recentTgtLangs: Array; +}; + +type SharedProps = Props & { + srcLangs: NamedLangs; + tgtLangs: NamedLangs; + swapLangs?: () => void; +}; + +const langListIdealRows = 12, + langListMaxWidths = 850, + langListMaxColumns = 6, + langListsBuffer = 50; +const langListMinColumnWidth = langListMaxWidths / langListMaxColumns; + +const MobileLanguageSelector = ({ + pairs, + srcLang, + setSrcLang, + tgtLang, + setTgtLang, + srcLangs, + tgtLangs, + swapLangs, +}: SharedProps): React.ReactElement => { + const { tLang } = useLocalization(); + + const onSrcLangChange = React.useCallback>( + ({ target: { value } }) => setSrcLang(value), + [setSrcLang], + ); + + const onTgtLangChange = React.useCallback>( + ({ target: { value } }) => setTgtLang(value), + [setTgtLang], + ); + + const srcLangOptions = React.useMemo( + () => ( + <> + {srcLangs.map(([code, name]) => ( + + ))} + + ), + [pairs, srcLangs], + ); + + const tgtLangOptions = React.useMemo( + () => ( + <> + {tgtLangs.map(([code, name]) => ( + + ))} + + ), + [pairs, srcLang, tgtLangs], + ); + + return ( + +
+ + {srcLangOptions} + + + + + + {tgtLangOptions} + +
+
+ ); +}; + +const LangsDropdown = ({ + langs, + numCols, + setLang, + validLang, +}: { + langs: NamedLangs; + numCols: number; + setLang: (code: string) => void; + validLang: (code: string) => boolean; +}): React.ReactElement => { + const langsPerCol = React.useMemo(() => { + let langsPerCol = Math.ceil(langs.length / numCols); + + for (let i = 0; i < numCols; i++) { + while (i * langsPerCol < langs.length && isVariant(langs[i * langsPerCol][0])) { + langsPerCol++; + } + } + + return langsPerCol; + }, [langs, numCols]); + + const langCols = []; + + for (let i = 0; i < numCols; i++) { + const numLang = langsPerCol * i; + const langElems: Array = []; + + for (let j = numLang; j < langs.length && j < numLang + langsPerCol; j++) { + const [code, name] = langs[j]; + const valid = !validLang || validLang(code); + langElems.push( + , + ); + } + langCols.push( +
+ {langElems} +
, + ); + } + + return ( + + {langCols} + + ); +}; + +const DesktopLanguageSelector = ({ + pairs, + srcLang, + setSrcLang, + tgtLang, + setTgtLang, + recentTgtLangs, + recentSrcLangs, + srcLangs, + tgtLangs, + swapLangs, +}: SharedProps): React.ReactElement => { + const locale = React.useContext(LocaleContext); + const { tLang } = useLocalization(); + + const srcLangsDropdownTriggerRef = React.createRef(); + const tgtLangsDropdownTriggerRef = React.createRef(); + + const [numSrcCols, setNumSrcCols] = React.useState(1); + const [numTgtCols, setNumTgtCols] = React.useState(1); + + React.useLayoutEffect(() => { + const refreshSizes = () => { + let maxSrcLangsWidth, maxTgtLangsWidth; + + const srcLangsDropdownOffset = srcLangsDropdownTriggerRef.current?.getBoundingClientRect().x || 0; + const tgtLangsDropdownOffset = tgtLangsDropdownTriggerRef.current?.getBoundingClientRect().x || 0; + const srcLangsDropdownWidth = srcLangsDropdownTriggerRef.current?.offsetWidth || 0; + const tgtLangsDropdownWidth = tgtLangsDropdownTriggerRef.current?.offsetWidth || 0; + + if (langDirection(locale) === 'ltr') { + maxSrcLangsWidth = window.innerWidth - srcLangsDropdownOffset - langListsBuffer; + maxTgtLangsWidth = tgtLangsDropdownOffset + tgtLangsDropdownWidth - langListsBuffer; + } else { + maxSrcLangsWidth = srcLangsDropdownOffset + srcLangsDropdownWidth - langListsBuffer; + maxTgtLangsWidth = window.innerWidth - tgtLangsDropdownOffset - langListsBuffer; + } + + maxSrcLangsWidth = Math.min(langListMaxWidths, maxSrcLangsWidth); + maxTgtLangsWidth = Math.min(langListMaxWidths, maxTgtLangsWidth); + + setNumSrcCols( + Math.max( + 1, + Math.min( + Math.ceil(srcLangs.length / langListIdealRows), + Math.floor(maxSrcLangsWidth / langListMinColumnWidth), + langListMaxColumns, + ), + ), + ); + setNumTgtCols( + Math.max( + 1, + Math.min( + Math.ceil(tgtLangs.length / langListIdealRows), + Math.floor(maxTgtLangsWidth / langListMinColumnWidth), + langListMaxColumns, + ), + ), + ); + }; + + window.addEventListener('resize', refreshSizes); + refreshSizes(); + + return () => window.removeEventListener('resize', refreshSizes); + }, [locale, tgtLangs.length, srcLangs.length]); + + const validTgtLang = React.useCallback((lang: string) => isPair(pairs, srcLang, lang), [pairs, srcLang]); + const validSrcLang = React.useCallback((lang: string) => !!pairs[lang] && pairs[lang].size > 0, [pairs]); + + const MAX_QUICK = 3; + + const visibleSrcLangs = React.useMemo(() => { + const uniq = (arr: string[]) => Array.from(new Set(arr)); + const fromRecents = (recentSrcLangs || []).filter(validSrcLang); + if (fromRecents.length) { + const pad = srcLangs + .map(([c]) => c) + .filter(validSrcLang) + .filter((c) => !fromRecents.includes(c)); + return uniq([srcLang, ...fromRecents, ...pad]).slice(0, MAX_QUICK); + } + const fallbacks = srcLangs.map(([c]) => c).filter(validSrcLang); + return uniq([srcLang, ...fallbacks]).slice(0, MAX_QUICK); + }, [recentSrcLangs, srcLangs, validSrcLang, srcLang]); + + const visibleTgtLangs = React.useMemo(() => { + const uniq = (arr: string[]) => Array.from(new Set(arr)); + const fromRecents = (recentTgtLangs || []).filter(validTgtLang); + if (fromRecents.length) { + const pad = tgtLangs + .map(([c]) => c) + .filter(validTgtLang) + .filter((c) => !fromRecents.includes(c)); + return uniq([tgtLang, ...fromRecents, ...pad]).slice(0, MAX_QUICK); + } + const fallbacks = tgtLangs.map(([c]) => c).filter(validTgtLang); + return uniq([tgtLang, ...fallbacks]).slice(0, MAX_QUICK); + }, [recentTgtLangs, tgtLangs, validTgtLang, tgtLang]); + + return ( + <> + + + + {visibleSrcLangs.map((lang) => ( + + ))} + + + + + + + + + + {visibleTgtLangs.map((lang) => ( + + ))} + + + + + + + + ); +}; + +const LanguageSelector = (props: Props): React.ReactElement => { + const { pairs, srcLang, setSrcLang, recentSrcLangs, setRecentSrcLangs, tgtLang, setTgtLang } = props; + + const swapLangs = React.useMemo( + () => + isPair(pairs, tgtLang, srcLang) + ? () => { + setSrcLang(tgtLang); + setTgtLang(srcLang); + } + : undefined, + [pairs, setSrcLang, setTgtLang, srcLang, tgtLang], + ); + + const mobileMediaQuery = React.useRef(window.matchMedia('(max-width: 768px)')); + const [showMobile, setShowMobile] = React.useState(mobileMediaQuery.current.matches); + React.useEffect(() => { + const handleMediaChange = ({ matches }: MediaQueryListEvent) => { + setShowMobile(matches); + }; + + const { current } = mobileMediaQuery; + current.addEventListener('change', handleMediaChange); + return () => current.removeEventListener('change', handleMediaChange); + }, []); + + const initializedBestSrc = React.useRef(false); + React.useEffect(() => { + if (initializedBestSrc.current) return; + let best = srcLang; + let bestSize = (pairs[srcLang] && pairs[srcLang].size) || 0; + const keys = Object.keys(pairs as Record>); + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + const size = (pairs[k] && pairs[k].size) || 0; + if (size > bestSize) { + best = k; + bestSize = size; + } + } + if (best && best !== srcLang) { + setSrcLang(best); + if (!isPair(pairs, best, tgtLang)) { + const it = pairs[best] && (pairs[best] as Set).values(); + const first = it ? it.next().value : undefined; + if (first) { + setTgtLang(first); + } + } + } + initializedBestSrc.current = true; + }, [pairs]); + + const SelectorComponent = showMobile ? MobileLanguageSelector : DesktopLanguageSelector; + + return ( + + {(sortedLanguageProps: ChildProps) => ( + + )} + + ); +}; + +export default LanguageSelector; diff --git a/src/components/dictionary/Paradigm.css b/src/components/dictionary/Paradigm.css new file mode 100644 index 000000000..c2288af93 --- /dev/null +++ b/src/components/dictionary/Paradigm.css @@ -0,0 +1,43 @@ +#content { + margin-left: 10%; + margin-right: 10%; + margin-bottom: 10%; +} + +th { + font-weight: normal; + background: #f2f2f2; + border: 1px #aaa solid; + text-align: left; + padding: 8px; +} + +td { + font-weight: bold; + border: 1px #aaa solid; + padding: 8px; + text-align: left; +} + +table { + font-family: arial, sans-serif; + width: 100%; + table-layout: fixed; + margin: 1em 1em 1em 0; + background: #f9f9f9; + border: 1px #aaa solid; + border-collapse: collapse; +} + +tr:nth-child(even) { + background-color: white; +} + +.table-container { + display: flex; + flex-direction: row; +} + +.table-container div.table:not(:last-child) { + margin-right: 1em; +} diff --git a/src/components/dictionary/Paradigm.tsx b/src/components/dictionary/Paradigm.tsx new file mode 100644 index 000000000..1d17c60b0 --- /dev/null +++ b/src/components/dictionary/Paradigm.tsx @@ -0,0 +1,169 @@ +import React, { useState, useEffect, useContext } from 'react'; +import axios, { CancelTokenSource } from 'axios'; +import Spinner from 'react-bootstrap/Spinner'; +import { APyContext } from '../../context'; +import { useLocalization, useLocalizationPOS } from '../../util/localization'; +import { languageRegistry } from './index'; +import './Paradigm.css'; + +interface ParadigmProps { + head: string; + lang: string; + mode: string; + onLoaded?: () => void; +} + +interface Block { + id?: string; + label: () => string; + tabcols?: string[]; + tabrows?: string[]; + tabdata?: { tags?: string; pretxt?: string }[][]; + tablist?: Array<{ label: string; tags: string; pretxt?: string }>; + subcats?: Block[]; +} + +const Paradigm: React.FC = ({ head, lang, mode, onLoaded }) => { + const apyFetch = useContext(APyContext); + const { t } = useLocalization(); + const { locale } = useLocalizationPOS(); + const [loading, setLoading] = useState(true); + const [blocks, setBlocks] = useState([]); + const [values, setValues] = useState>({}); + const availableLangs = Object.keys(languageRegistry); + const pluginLang = availableLangs.includes(lang) ? lang : availableLangs[0]; + const plugin = languageRegistry[pluginLang]; + + useEffect(() => { + if (!plugin) return; + let isMounted = true; + const cancelers: CancelTokenSource[] = []; + + const raw = plugin.addParadigms({ head, mode, locale, t, apyFetch }) || []; + setBlocks(Array.isArray(raw) ? raw : []); + setLoading(false); + if (!Array.isArray(raw) || !raw.length) { + onLoaded?.(); + return; + } + + const getLeaves = (blocks: Block[]): Block[] => blocks.flatMap((b) => (b.subcats ? getLeaves(b.subcats) : [b])); + + const leaves = getLeaves(raw); + const dataCells = leaves.flatMap((b) => b.tabdata ?? []).flat(); + const listCells = leaves.flatMap((b) => b.tablist ?? []); + const fetchCells = [...dataCells, ...listCells].filter((cell) => cell.tags); + + if (!fetchCells.length) { + onLoaded?.(); + return; + } + + setLoading(true); + const out: Record = {}; + const lemma = head.replace(/<[^>]+>/g, ''); + const origTags = Array.from(head.matchAll(/<([^>]+)>/g), (m) => m[1]); + + Promise.all( + fetchCells.map(async (cell) => { + const seq = plugin.parseTags(origTags, cell.tags!); + const pattern = '^' + lemma + seq.map((x) => `<${x}>`).join('') + '$'; + const [ctr, req] = apyFetch('generate', { + lang: plugin.backendLangCode, + q: pattern, + }); + cancelers.push(ctr); + try { + const data = (await req).data as Array<[string, string]>; + if (data.length && !data[0][0].startsWith('#')) { + out[cell.tags!] = data[0][0]; + } + } catch {} + }), + ).then(() => { + if (isMounted) { + setValues(out); + setLoading(false); + onLoaded?.(); + } + }); + + return () => { + isMounted = false; + cancelers.forEach((c) => c.cancel()); + }; + }, [head, lang, locale, mode, t, apyFetch, plugin, onLoaded]); + + const RenderBlock: React.FC<{ block: Block; level: number }> = ({ block, level }) => { + const Heading = level === 0 ? 'h4' : level === 1 ? 'h5' : 'h6'; + + return ( +
+ {t(block.label())} + {block.subcats ? ( + block.subcats.map((sub, i) => ) + ) : block.tablist ? ( + + + {block.tablist.map((item, k) => { + const val = values[item.tags]; + const content = item.pretxt && val ? `${item.pretxt} ${val}` : val ?? item.pretxt ?? ''; + return ( + + + + + ); + })} + +
{t(item.label)}{content}
+ ) : ( + + + + + ))} + + + + {block.tabrows?.map((r, ri) => ( + + + {block.tabdata![ri].map((cell, ci) => { + const val = values[cell.tags!]; + const content = cell.pretxt && val ? `${cell.pretxt} ${val}` : val ?? cell.pretxt ?? ''; + return ; + })} + + ))} + +
+ {block.tabcols?.map((c, ci) => ( + {t(c)}
{t(r)}{content}
+ )} +
+ ); + }; + + if (!plugin) { + return
{t('No_paradigms_for_language', { lang })}
; + } + if (loading) return ; + if (!blocks.length) { + return ( +
+ {t('No_pos_found')} +
+ ); + } + + return ( +
+ {blocks.map((blk, i) => ( + + ))} +
+ ); +}; + +export default Paradigm; diff --git a/src/components/dictionary/Word.css b/src/components/dictionary/Word.css new file mode 100644 index 000000000..4110103b1 --- /dev/null +++ b/src/components/dictionary/Word.css @@ -0,0 +1,78 @@ +.word-card { + margin-top: 1rem; + padding: 1rem; + background-color: white; + border-radius: 0.5rem; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); +} + +.word-header { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.5rem; +} + +.word-text { + font-size: 1.5rem; + font-weight: bold; + color: #007bff; +} + +.word-pos { + font-size: 1rem; + font-style: italic; + color: silver; +} + +.word-definitions { + padding-left: 1.25rem; + margin: 0; +} + +.definition-item { + cursor: pointer; + transition: color 0.2s ease; +} + +.definition-item:hover { + text-decoration: underline; + color: #0056b3; +} + +.expand-button { + padding: 0.5rem 1rem; + font-size: 1rem; + background-color: #f0f0f0; + border: none; + border-radius: 0.25rem; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.expand-button:hover { + background-color: #e0e0e0; +} + +.expand-controls { + margin-top: 1rem; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.word-paradigm { + margin-top: 1.5rem; + padding: 1rem; + background: #fafafa; + border-radius: 0.25rem; +} + +.word-paradigm .paradigm-container { + margin: 0; + padding: 0; +} + +#mode-dropdown { + color: #000; +} diff --git a/src/components/dictionary/Word.tsx b/src/components/dictionary/Word.tsx new file mode 100644 index 000000000..4b2db7978 --- /dev/null +++ b/src/components/dictionary/Word.tsx @@ -0,0 +1,112 @@ +import React, { useState, useEffect, useContext } from 'react'; +import './Word.css'; +import { useLocalizationPOS } from '../../util/localization'; +import { getPosTag } from '../../util/posLocalization'; +import { useLocalization } from '../../util/localization'; +import Spinner from 'react-bootstrap/Spinner'; +import Dropdown from 'react-bootstrap/Dropdown'; +import Paradigm from './Paradigm'; +import { languageRegistry } from './index'; +import { APyContext } from '../../context'; + +export interface WordProps { + head: string; + definitions: string[]; + lang: string; + onDefinitionClick?: (definition: string, index: number) => void; +} + +const Word: React.FC = ({ head, definitions, lang, onDefinitionClick }) => { + const { locale } = useLocalizationPOS(); + const { t } = useLocalization(); + const apyFetch = useContext(APyContext); + const [expanded, setExpanded] = useState(false); + const [loadingParadigm, setLoadingParadigm] = useState(false); + + const plugin = languageRegistry[lang] || null; + const code = locale.split('-')[0].toLowerCase(); + const availableModes = plugin?.getAvailableModes ? plugin.getAvailableModes(locale) : []; + const [mode, setMode] = useState(availableModes[0] || ''); + + useEffect(() => { + if (availableModes.length && !availableModes.includes(mode)) { + setMode(availableModes[0]); + } + }, [locale, availableModes]); + + const tagRe = /<([^>]+)>/g; + const tags: string[] = []; + let m: RegExpExecArray | null; + while ((m = tagRe.exec(head))) tags.push(m[1]); + + const word = head.replace(/<[^>]+>/g, ''); + const cleanDefs = definitions.map((def) => def.replace(/<[^>]+>/g, '')).filter((def) => !/^\(.*\)$/.test(def)); + const displayTag = tags.length ? getPosTag(locale, tags.join('.')) : null; + + const handleToggle = () => { + if (!expanded) { + setExpanded(true); + setLoadingParadigm(true); + } else { + setExpanded(false); + } + }; + + const rawBlocks = plugin ? plugin.addParadigms({ head, mode, locale, t, apyFetch }) : []; + const hasParadigms = Array.isArray(rawBlocks) && rawBlocks.length > 0; + const showExpand = hasParadigms; + const showDropdown = hasParadigms && availableModes.length > 1; + + return ( +
+
+ {word} + {displayTag && {displayTag}} +
+
    + {cleanDefs.map((def, i) => ( +
  1. onDefinitionClick?.(def, i)}> + {def} +
  2. + ))} +
+ {showExpand && ( +
+ + {showDropdown && expanded && ( + typeof key === 'string' && setMode(key)}> + + {mode} + + + {availableModes.map((mk) => ( + + {mk} + + ))} + + + )} +
+ )} + {showExpand && expanded && ( +
+ setLoadingParadigm(false)} /> +
+ )} +
+ ); +}; + +export default Word; diff --git a/src/components/dictionary/index.ts b/src/components/dictionary/index.ts new file mode 100644 index 000000000..2053a3d50 --- /dev/null +++ b/src/components/dictionary/index.ts @@ -0,0 +1,11 @@ +import Dictionary from './Dictionary'; +import { spaPlugin } from './langs/spa'; +import { uumPlugin } from './langs/uum'; +import { LanguagePlugin } from './types'; + +export const languageRegistry: Record = { + "spa": spaPlugin, + "uum": uumPlugin, +}; + +export default Dictionary; diff --git a/src/components/dictionary/langs/spa.ts b/src/components/dictionary/langs/spa.ts new file mode 100644 index 000000000..3f1cd1db4 --- /dev/null +++ b/src/components/dictionary/langs/spa.ts @@ -0,0 +1,186 @@ +export interface SpaLabels { + sg: string; + pl: string; + p1: string; + p2: string; + p3: string; + labels: Record; +} + +export const spaLabels: Record> = { + eng: { + Linguist: { + sg: 'Singular', + pl: 'Plural', + p1: '1st', + p2: '2nd', + p3: '3rd', + labels: { + 'non-personal': 'Non‑personal forms', + personal: 'Personal forms', + indicative: 'Indicative mode', + subjunctive: 'Subjunctive mode', + imperative: 'Imperative mode', + inf: 'Simple infinitive', + 'inf.comp': 'Compound infinitive', + ger: 'Simple gerund', + 'ger.comp': 'Compound gerund', + pp: 'Past participle', + pri: 'Present', + pii: 'Past imperfect (pretérito imperfecto)', + ifi: 'Past definite (pretérito perfecto simple)', + fti: 'Simple future', + cni: 'Simple conditional', + 'pri.comp': 'Compound past definite (pretérito perfecto compuesto)', + 'pii.comp': 'Compound past perfect (pretérito pluscuamperfecto)', + 'ifi.comp': 'Compound past perfect anterior (pretérito anterior)', + 'fti.comp': 'Compound future', + 'cni.comp': 'Compound conditional', + prs: 'Present', + pis: 'Past imperfect', + }, + }, + }, +}; + +const auxForms: Record = { + pri: ['he', 'hemos', 'has', 'habéis', 'ha', 'han'], + pii: ['había', 'habíamos', 'habías', 'habíais', 'había', 'habían'], + ifi: ['hube', 'hubimos', 'hubiste', 'hubisteis', 'hubo', 'hubieron'], + fti: ['habré', 'habremos', 'habrás', 'habréis', 'habrá', 'habrán'], + cni: ['habría', 'habríamos', 'habrías', 'habríais', 'habría', 'habrían'], + prs: ['haya', 'hayamos', 'hayas', 'hayáis', 'haya', 'hayan'], + pis: ['hubiera/hubiese', 'hubiéramos/hubiésemos', 'hubieras/hubieses', 'hubierais/hubieseis', 'hubiera/hubiese', 'hubieran/hubiesen'], + fts: ['hubiere', 'hubiéremos', 'hubieres', 'hubiereis', 'hubiere', 'hubieren'], +}; + +function spaP123Table( + ctx: { labels: SpaLabels; t: (key: string) => string }, + suffix: string, + labelKey: string +): ParadigmBlock { + const { labels: m, t } = ctx; + return { + id: suffix, + label: () => t(m.labels[labelKey]), + tabcols: [m.sg, m.pl].map(k => t(k)), + tabrows: [m.p1, m.p2, m.p3].map(k => t(k)), + tabdata: [ + [{ tags: `${suffix}.p1.sg` }, { tags: `${suffix}.p1.pl` }], + [{ tags: `${suffix}.p2.sg` }, { tags: `${suffix}.p2.pl` }], + [{ tags: `${suffix}.p3.sg` }, { tags: `${suffix}.p3.pl` }], + ], + }; +} + +function spaCompound( + ctx: { labels: SpaLabels; t: (key: string) => string }, + auxKey: string, + labelKey: string +): ParadigmBlock { + const { labels: m, t } = ctx; + const forms = auxForms[auxKey as keyof typeof auxForms] || []; + const [p1sg, p1pl, p2sg, p2pl, p3sg, p3pl] = forms; + return { + id: `${auxKey}.comp`, + label: () => t(m.labels[labelKey]), + tabcols: [m.sg, m.pl].map(k => t(k)), + tabrows: [m.p1, m.p2, m.p3].map(k => t(k)), + tabdata: [ + [{ pretxt: p1sg, tags: 'pp.m.sg' }, { pretxt: p1pl, tags: 'pp.m.sg' }], + [{ pretxt: p2sg, tags: 'pp.m.sg' }, { pretxt: p2pl, tags: 'pp.m.sg' }], + [{ pretxt: p3sg, tags: 'pp.m.sg' }, { pretxt: p3pl, tags: 'pp.m.sg' }], + ], + }; +} + +function buildSpaBlocks( + ctx: { labels: SpaLabels; t: (key: string) => string } +): ParadigmBlock[] { + const { labels: m, t } = ctx; + + const nonPersonal: ParadigmBlock = { + id: 'non-personal', + label: () => t(m.labels['non-personal']), + tablist: [ + { label: t(m.labels.inf), tags: 'inf' }, + { label: t(m.labels['inf.comp']), pretxt: 'habiendo', tags: 'pp.m.sg' }, + { label: t(m.labels.ger), tags: 'ger' }, + { label: t(m.labels['ger.comp']), pretxt: 'habiendo', tags: 'pp.m.sg' }, + { label: t(m.labels.pp), tags: 'pp.m.sg' }, + ], + }; + + const personal: ParadigmBlock = { + id: 'personal', + label: () => t(m.labels.personal), + subcats: [ + { + id: 'indicative', + label: () => t(m.labels.indicative), + subcats: [ + spaP123Table(ctx, 'pri', 'pri'), + spaP123Table(ctx, 'pii', 'pii'), + spaP123Table(ctx, 'ifi', 'ifi'), + spaP123Table(ctx, 'fti', 'fti'), + spaP123Table(ctx, 'cni', 'cni'), + spaCompound(ctx, 'pri', 'pri.comp'), + spaCompound(ctx, 'pii', 'pii.comp'), + spaCompound(ctx, 'ifi', 'ifi.comp'), + spaCompound(ctx, 'fti', 'fti.comp'), + spaCompound(ctx, 'cni', 'cni.comp'), + ], + }, + { + id: 'subjunctive', + label: () => t(m.labels.subjunctive), + subcats: [ + spaP123Table(ctx, 'prs', 'prs'), + spaP123Table(ctx, 'pis', 'pis'), + spaCompound(ctx, 'prs', 'pri.comp'), + spaCompound(ctx, 'pis', 'pii.comp'), + spaCompound(ctx, 'fts', 'fti.comp'), + ], + }, + { + id: 'imperative', + label: () => t(m.labels.imperative), + tabcols: [m.sg, m.pl].map(k => t(k)), + tabrows: [m.p1, m.p2, m.p3].map(k => t(k)), + tabdata: [ + [{}, { tags: 'imp.p1.pl' }], + [{ tags: 'imp.p2.sg' }, { tags: 'imp.p2.pl' }], + [{ tags: 'imp.p3.sg' }, { tags: 'imp.p3.pl' }], + ], + }, + ], + }; + + return [nonPersonal, personal]; +} + +export function add_spa( + ctx: { labels: SpaLabels; t: (key: string) => string } +): Record { + return { vaux: [], vblex: buildSpaBlocks(ctx) }; +} + +export const spaPlugin: LanguagePlugin = { + backendLangCode: 'spa', + addParadigms({ head, mode, locale, t }) { + const modes = spaLabels.eng; + const labelsForMode = modes[mode] || modes.Linguist; + const blocksMap = add_spa({ labels: labelsForMode, t }); + const origTags = Array.from(head.matchAll(/<([^>]+)>/g), m => m[1]); + if (origTags.includes('vblex')) { + return blocksMap.vblex; + } + return []; + }, + parseTags(origTags: string[], cell: string): string[] { + if (origTags.includes('vblex')) { + return ['vblex', ...cell.split('.')]; + } + return cell.split('.'); + }, +}; diff --git a/src/components/dictionary/langs/uum.ts b/src/components/dictionary/langs/uum.ts new file mode 100644 index 000000000..a625c751f --- /dev/null +++ b/src/components/dictionary/langs/uum.ts @@ -0,0 +1,692 @@ +export interface UumLabels { + sg: string; + pl: string; + p1?: string; + p2?: string; + p3?: string; + p1sg?: string; + p1pl?: string; + p2sg?: string; + p2pl?: string; + p3sg?: string; + p3pl?: string; + cases: Record; + labels: Record; + 'poss-sg': Record; + 'poss-pl': Record; +} + +export const uumLabels: Record> = { + ukr: { + 'Лінгвіст': { + sg: 'Однина', + pl: 'Множина', + p1: '1-ша', + p2: '2-га', + p3: '3-тя', + cases: { + nom: 'Називний', + acc: 'Знахідний', + dat: 'Давальний', + loc: 'Місцевий', + gen: 'Родовий', + abl: 'Відмінок походження', + ins: 'Орудний', + term: 'Кінцевий', + abe: 'Безвідмінковий', + }, + labels: { + 'non-personal': 'Неперсональні форми', + pres: 'Теперішній час', + past: 'Минулий час', + futs: 'Майбутній час', + fut: 'Майбутній недоконаний', + fdi: 'Майбутній доконаний', + 'pres.cni': 'Умовний', + imp: 'Наказовий', + 'noun-cases': 'Відмінки', + 'noun-poss': 'Присвійність', + 'noun-poss-sg': 'Однина', + 'noun-poss-pl': 'Множина', + affirmative: 'Стверджувальний', + negative: 'Заперечний', + infinitive: 'Інфінітив', + participle: 'Дієприкметник', + converb: 'Дієприслівник', + }, + 'poss-sg': { + p1sg: '1-ша', + p2sg: '2-га', + p3sg: '3-тя', + p1pl: '1-ша', + p2pl: '2-га', + p3pl: '3-тя', + }, + 'poss-pl': { + p1sg: '1-ша', + p2sg: '2-га', + p3sg: '3-тя', + p1pl: '1-ша', + p2pl: '2-га', + p3pl: '3-тя', + }, + }, + 'Учень': { + sg: 'Однина', + pl: 'Множина', + p1sg: 'я', + p2sg: 'ти', + p3sg: 'він/вона', + p1pl: 'ми', + p2pl: 'ви', + p3pl: 'вони', + cases: { + nom: 'Називний', + acc: 'Знахідний', + dat: 'Давальний', + loc: 'Місцевий', + gen: 'Родовий', + abl: 'Відмінок походження', + ins: 'Орудний', + term: 'Кінцевий', + abe: 'Безвідмінковий', + }, + labels: { + 'non-personal': 'Неперсональні форми', + pres: 'Теперішній час', + past: 'Минулий час', + futs: 'Майбутній час', + fut: 'Майбутній недоконаний', + fdi: 'Майбутній доконаний', + 'pres.cni': 'Умовний', + imp: 'Наказовий', + 'noun-cases': 'Відмінки', + 'noun-poss': 'Присвійність', + 'noun-poss-sg': 'Іменник в однині', + 'noun-poss-pl': 'Іменник у множині', + affirmative: 'Стверджувальний', + negative: 'Заперечний', + infinitive: 'Інфінітив', + participle: 'Дієприкметник', + converb: 'Дієприслівник', + }, + 'poss-sg': { + p1sg: 'мій', + p2sg: 'твій', + p3sg: 'його/її', + p1pl: 'наш', + p2pl: 'ваш', + p3pl: 'їхній', + }, + 'poss-pl': { + p1sg: 'мої', + p2sg: 'твої', + p3sg: 'його/її', + p1pl: 'наші', + p2pl: 'ваші', + p3pl: 'їхні', + }, + }, + }, + eng: { + Linguist: { + sg: 'Singular', + pl: 'Plural', + p1: '1st', + p2: '2nd', + p3: '3rd', + cases: { + nom: 'Nominative', + acc: 'Accusative', + dat: 'Dative', + loc: 'Locative', + gen: 'Genitive', + abl: 'Ablative', + ins: 'Instrumental', + term: 'Terminative', + abe: 'Abessive', + }, + labels: { + 'non-personal': 'Non-personal forms', + pres: 'Present', + past: 'Past', + futs: 'Future', + fut: 'Future indefinite', + fdi: 'Future definite', + 'pres.cni': 'Conditional', + imp: 'Imperative', + 'noun-cases': 'Cases', + 'noun-poss': 'Possession', + 'noun-poss-sg': 'Singular', + 'noun-poss-pl': 'Plural', + affirmative: 'Affirmative', + negative: 'Negative', + infinitive: 'Infinitive', + participle: 'Participle', + converb: 'Converb', + }, + 'poss-sg': { + p1sg: '1sg', + p2sg: '2sg', + p3sg: '3sg', + p1pl: '1pl', + p2pl: '2pl', + p3pl: '3pl', + }, + 'poss-pl': { + p1sg: '1sg', + p2sg: '2sg', + p3sg: '3sg', + p1pl: '1pl', + p2pl: '2pl', + p3pl: '3pl', + }, + }, + Learner: { + sg: 'Singular', + pl: 'Plural', + p1sg: 'I', + p2sg: 'you', + p3sg: 'he/she', + p1pl: 'we', + p2pl: 'you all', + p3pl: 'they', + cases: { + nom: 'Nominative', + acc: 'Accusative', + dat: 'Dative', + loc: 'Locative', + gen: 'Genitive', + abl: 'Ablative', + ins: 'Instrumental', + term: 'Terminative', + abe: 'Abessive', + }, + labels: { + 'non-personal': 'Non-personal forms', + pres: 'Present', + past: 'Past', + futs: 'Future', + fut: 'Future indefinite', + fdi: 'Future definite', + 'pres.cni': 'Conditional', + imp: 'Imperative', + 'noun-cases': 'Cases', + 'noun-poss': 'Possession', + 'noun-poss-sg': 'Singular possessed noun', + 'noun-poss-pl': 'Plural possessed noun', + affirmative: 'Affirmative', + negative: 'Negative', + infinitive: 'Infinitive', + participle: 'Participle', + converb: 'Converb', + }, + 'poss-sg': { + p1sg: 'my', + p2sg: 'your', + p3sg: 'his/her', + p1pl: 'our', + p2pl: 'your', + p3pl: 'their', + }, + 'poss-pl': { + p1sg: 'my (plural)', + p2sg: 'your (plural)', + p3sg: 'his/her (plural)', + p1pl: 'our (plural)', + p2pl: 'your (plural)', + p3pl: 'their (plural)', + }, + }, + }, + deu: { + 'Sprachwissenschaftler': { + sg: 'Singular', + pl: 'Plural', + p1: '1. Person', + p2: '2. Person', + p3: '3. Person', + cases: { + nom: 'Nominativ', + acc: 'Akkusativ', + dat: 'Dativ', + loc: 'Lokativ', + gen: 'Genitiv', + abl: 'Ablativ', + ins: 'Instrumentalis', + term: 'Terminativ', + abe: 'Abessiv', + }, + labels: { + 'non-personal': 'Nicht-personale Formen', + pres: 'Präsens', + past: 'Präteritum', + futs: 'Zukunft', + fut: 'Futur I', + fdi: 'Futur II', + 'pres.cni': 'Konjunktiv II', + imp: 'Imperativ', + 'noun-cases': 'Kasus', + 'noun-poss': 'Possessivformen', + 'noun-poss-sg': 'Singular', + 'noun-poss-pl': 'Plural', + affirmative: 'Bejahend', + negative: 'Verneinend', + infinitive: 'Infinitiv', + participle: 'Partizip', + converb: 'Konverb', + }, + 'poss-sg': { + p1sg: '1sg', + p2sg: '2sg', + p3sg: '3sg', + p1pl: '1pl', + p2pl: '2pl', + p3pl: '3pl', + }, + 'poss-pl': { + p1sg: '1sg', + p2sg: '2sg', + p3sg: '3sg', + p1pl: '1pl', + p2pl: '2pl', + p3pl: '3pl', + }, + }, + 'Lerner': { + sg: 'Singular', + pl: 'Plural', + p1sg: 'ich', + p2sg: 'du', + p3sg: 'er/sie/es', + p1pl: 'wir', + p2pl: 'ihr', + p3pl: 'sie/Sie', + cases: { + nom: 'Nominativ', + acc: 'Akkusativ', + dat: 'Dativ', + loc: 'Lokativ', + gen: 'Genitiv', + abl: 'Ablativ', + ins: 'Instrumentalis', + term: 'Terminativ', + abe: 'Abessiv', + }, + labels: { + 'non-personal': 'Nicht-personale Formen', + pres: 'Gegenwart', + past: 'Vergangenheit', + futs: 'Zukunft', + fut: 'Futur I', + fdi: 'Futur II', + 'pres.cni': 'Konjunktiv II', + imp: 'Befehlsform', + 'noun-cases': 'Fälle', + 'noun-poss': 'Besitzanzeige', + 'noun-poss-sg': 'Einzahl (Besitz)', + 'noun-poss-pl': 'Mehrzahl (Besitz)', + affirmative: 'Bejahung', + negative: 'Verneinung', + infinitive: 'Grundform', + participle: 'Partizip', + converb: 'Konverb', + }, + 'poss-sg': { + p1sg: 'mein', + p2sg: 'dein', + p3sg: 'sein/ihr/sein', + p1pl: 'unser', + p2pl: 'euer', + p3pl: 'ihr/Ihr', + }, + 'poss-pl': { + p1sg: 'meine', + p2sg: 'deine', + p3sg: 'seine/ihre/seine', + p1pl: 'unsere', + p2pl: 'eure', + p3pl: 'ihre/Ihre', + }, + }, + }, + rus: { + 'Лингвист': { + sg: 'Единственное число', + pl: 'Множественное число', + p1: '1-е лицо', + p2: '2-е лицо', + p3: '3-е лицо', + cases: { + nom: 'Именительный', + acc: 'Винительный', + dat: 'Дательный', + loc: 'Местный', + gen: 'Родительный', + abl: 'Исходный', + ins: 'Творительный', + term: 'Предел', + abe: 'Безналичный', + }, + labels: { + 'non-personal': 'Неличные формы', + pres: 'Настоящее время', + past: 'Прошедшее время', + futs: 'Будущее время', + fut: 'Будущее неопределенное', + fdi: 'Будущее определенное', + 'pres.cni': 'Условное', + imp: 'Повелительное', + 'noun-cases': 'Падежи', + 'noun-poss': 'Притяжательность', + 'noun-poss-sg': 'Единственное', + 'noun-poss-pl': 'Множественное', + affirmative: 'Утвердительный', + negative: 'Отрицательный', + infinitive: 'Инфинитив', + participle: 'Причастие', + converb: 'Деепричастие', + }, + 'poss-sg': { + p1sg: '1-е Единственное', + p2sg: '2-е Единственное', + p3sg: '3-е Единственное', + p1pl: '1-е Множественное', + p2pl: '2-е Множественное', + p3pl: '3-е Множественное', + }, + 'poss-pl': { + p1sg: '1-е Единственное', + p2sg: '2-е Единственное', + p3sg: '3-е Единственное', + p1pl: '1-е Множественное', + p2pl: '2-е Множественное', + p3pl: '3-е Множественное', + }, + }, + 'Ученик': { + sg: 'Единственное число', + pl: 'Множественное число', + p1sg: 'я', + p2sg: 'ты', + p3sg: 'он/она', + p1pl: 'мы', + p2pl: 'вы', + p3pl: 'они', + cases: { + nom: 'Именительный', + acc: 'Винительный', + dat: 'Дательный', + loc: 'Местный', + gen: 'Родительный', + abl: 'Исходный', + ins: 'Творительный', + term: 'Предел', + abe: 'Безналичный', + }, + labels: { + 'non-personal': 'Неличные формы', + pres: 'Настоящее время', + past: 'Прошедшее время', + futs: 'Будущее время', + fut: 'Будущее несовершенное', + fdi: 'Будущее совершенное', + 'pres.cni': 'Условное', + imp: 'Повелительное', + 'noun-cases': 'Падежи', + 'noun-poss': 'Притяжательность', + 'noun-poss-sg': 'Существительное в единственном числе', + 'noun-poss-pl': 'Существительное во множественном числе', + affirmative: 'Утвердительная', + negative: 'Отрицательная', + infinitive: 'Инфинитив', + participle: 'Причастие', + converb: 'Деепричастие', + }, + 'poss-sg': { + p1sg: 'мой', + p2sg: 'твой', + p3sg: 'его/её', + p1pl: 'наш', + p2pl: 'ваш', + p3pl: 'их', + }, + 'poss-pl': { + p1sg: 'мои', + p2sg: 'твои', + p3sg: 'его/её', + p1pl: 'наши', + p2pl: 'ваши', + p3pl: 'их', + }, + }, + }, +}; + +function add_uum( + ctx: { labels: UumLabels; t: (key: string) => string } +): Record { + const { labels: m, t } = ctx; + + function uumFinVb(tgs: string, lab: string): ParadigmBlock { + const rowLabels = + 'p1' in m + ? [ + `${m.p1} ${m.sg}`, + `${m.p1} ${m.pl}`, + `${m.p2} ${m.sg}`, + `${m.p2} ${m.pl}`, + `${m.p3} ${m.sg}`, + `${m.p3} ${m.pl}`, + ] + : [m.p1sg!, m.p1pl!, m.p2sg!, m.p2pl!, m.p3sg!, m.p3pl!]; + + return { + id: tgs.replace(/\./g, '-'), + label: () => t(m.labels[lab] || lab), + tabcols: [m.labels.affirmative, m.labels.negative].map(k => t(k)), + tabrows: rowLabels.map(lbl => t(lbl)), + tabdata: [ + [{ tags: `${tgs}.p1.sg` }], + [{ tags: `${tgs}.p1.pl` }], + [{ tags: `${tgs}.p2.sg` }], + [{ tags: `${tgs}.p2.pl` }], + [{ tags: `${tgs}.p3.sg` }], + [{ tags: `${tgs}.p3.pl` }], + ].map((row, i) => [row[0], { tags: `neg.${row[0].tags}` }]), + } + } + + const mkImpRows = () => + 'p1' in m + ? [ + `${m.p1} ${m.sg}`, + `${m.p1} ${m.pl}`, + `${m.p2} ${m.sg}`, + `${m.p2} ${m.pl}`, + ] + : [m.p1sg!, m.p1pl!, m.p2sg!, m.p2pl!]; + + return { + vaux: [], + + verb_iv: [ + { + id: 'non-personal', + label: () => t(m.labels['non-personal']), + tabcols: [m.labels.affirmative, m.labels.negative].map(k => t(k)), + tabrows: [m.labels.infinitive, m.labels.participle, m.labels.converb].map(k => t(k)), + tabdata: [ + [{ tags: 'inf' }], + [{ tags: 'pp' }], + [{ tags: 'tsg' }], + ].map((row, i) => [row[0], { tags: `neg.${row[0].tags}` }]), + }, + uumFinVb('pres', 'pres'), + uumFinVb('past', 'past'), + { + id: 'future', + label: () => t(m.labels.futs), + subcats: [uumFinVb('fut', 'fut'), uumFinVb('fdi', 'fdi')], + }, + uumFinVb('pres.cni', 'pres.cni'), + { + id: 'imp', + label: () => t(m.labels.imp), + tabcols: [m.labels.affirmative, m.labels.negative].map(k => t(k)), + tabrows: mkImpRows().map(lbl => t(lbl)), + tabdata: mkImpRows().map((lbl, i) => [ + { tags: `imp.p${i < 2 ? 1 : 2}.${i % 2 === 0 ? 'sg' : 'pl'}` }, + { tags: `neg.imp.p${i < 2 ? 1 : 2}.${i % 2 === 0 ? 'sg' : 'pl'}` }, + ]), + }, + ], + + verb_tv: [ + { + id: 'non-personal', + label: () => t(m.labels['non-personal']), + tabcols: [m.labels.affirmative, m.labels.negative].map(k => t(k)), + tabrows: [m.labels.infinitive, m.labels.participle, m.labels.converb].map(k => t(k)), + tabdata: [ + [{ tags: 'inf' }], + [{ tags: 'pp' }], + [{ tags: 'tsg' }], + ].map((row, i) => [row[0], { tags: `neg.${row[0].tags}` }]), + }, + uumFinVb('pres', 'pres'), + uumFinVb('past', 'past'), + { + id: 'future', + label: () => t(m.labels.futs), + subcats: [uumFinVb('fut', 'fut'), uumFinVb('fdi', 'fdi')], + }, + uumFinVb('pres.cni', 'pres.cni'), + { + id: 'imp', + label: () => t(m.labels.imp), + tabcols: [m.labels.affirmative, m.labels.negative].map(k => t(k)), + tabrows: mkImpRows().map(lbl => t(lbl)), + tabdata: mkImpRows().map((lbl, i) => [ + { tags: `imp.p${i < 2 ? 1 : 2}.${i % 2 === 0 ? 'sg' : 'pl'}` }, + { tags: `neg.imp.p${i < 2 ? 1 : 2}.${i % 2 === 0 ? 'sg' : 'pl'}` }, + ]), + }, + ], + + noun: [ + { + id: 'noun-cases', + label: () => t(m.labels['noun-cases']), + tabcols: [m.sg, m.pl].map(k => t(k)), + tabrows: Object.values(m.cases).map(k => t(k)), + tabdata: Object.keys(m.cases).map(c => [ + { tags: c }, + { tags: `pl.${c}` }, + ]), + }, + { + id: 'noun-poss', + label: () => t(m.labels['noun-poss']), + subcats: [ + { + id: 'noun-poss-sg', + label: () => t(m.labels['noun-poss-sg']), + tabcols: Object.values(m['poss-sg']).map(k => t(k)), + tabrows: Object.values(m.cases).map(k => t(k)), + tabdata: Object.keys(m.cases).map(c => + Object.keys(m['poss-sg']).map(p => ({ tags: `px${p.slice(1)}.${c}` })) + ), + }, + { + id: 'noun-poss-pl', + label: () => t(m.labels['noun-poss-pl']), + tabcols: Object.values(m['poss-pl']).map(k => t(k)), + tabrows: Object.values(m.cases).map(k => t(k)), + tabdata: Object.keys(m.cases).map(c => + Object.keys(m['poss-pl']).map(p => ({ tags: `pl.px${p.slice(1)}.${c}` })) + ), + }, + ], + }, + ], + + pnoun: [ + { + id: 'pnoun-cases', + label: () => t(m.labels['noun-cases']), + tabcols: [m.sg, m.pl].map(k => t(k)), + tabrows: Object.values(m.cases).map(k => t(k)), + tabdata: Object.keys(m.cases).map(c => [ + { tags: c }, + { tags: `pl.${c}` }, + ]), + }, + { + id: 'pnoun-poss', + label: () => t(m.labels['noun-poss']), + subcats: [ + { + id: 'pnoun-poss-sg', + label: () => t(m.labels['noun-poss-sg']), + tabcols: Object.values(m['poss-sg']).map(k => t(k)), + tabrows: Object.values(m.cases).map(k => t(k)), + tabdata: Object.keys(m.cases).map(c => + Object.keys(m['poss-sg']).map(p => ({ tags: `px${p.slice(1)}.${c}` })) + ), + }, + { + id: 'pnoun-poss-pl', + label: () => t(m.labels['noun-poss-pl']), + tabcols: Object.values(m['poss-pl']).map(k => t(k)), + tabrows: Object.values(m.cases).map(k => t(k)), + tabdata: Object.keys(m.cases).map(c => + Object.keys(m['poss-pl']).map(p => ({ tags: `pl.px${p.slice(1)}.${c}` })) + ), + }, + ], + }, + ], + } +} + +export function parseTags(origTags: string[], cellTags: string): string[] { + const parts = cellTags.split('.'); + const first = origTags[0] || ''; + if (first === 'np' || first.startsWith('np.')) return [...origTags, ...parts]; + if (first.startsWith('v')) return [...origTags, ...parts]; + if (parts.length === 3 && parts[0] === 'pl') return ['n', 'pl', parts[1], parts[2]]; + if (parts.length === 2 && parts[0].startsWith('px')) return ['n', parts[0], parts[1]]; + if (parts.length === 2 && parts[0] === 'pl') return ['n', 'pl', parts[1]]; + return ['n', parts[0]]; +} + +const defaultLangKey = Object.keys(uumLabels)[0]; +const defaultModes = uumLabels[defaultLangKey]; + +export const uumPlugin: LanguagePlugin = { + backendLangCode: 'uum', + getAvailableModes(locale: string): string[] { + const code = locale.split('-')[0].toLowerCase(); + const modesForLang = uumLabels[code] ?? defaultModes; + return Object.keys(modesForLang); + }, + addParadigms({ head, mode, locale, t, apyFetch }: AddParadigmsArgs): ParadigmBlock[] { + const code = locale.split('-')[0].toLowerCase(); + const modesForLang = uumLabels[code] ?? defaultModes; + const modeKeys = Object.keys(modesForLang); + const fallbackMode = modeKeys[0]; + const labelsForMode = modesForLang[mode] ?? modesForLang[fallbackMode]; + const blocksMap = add_uum({ labels: labelsForMode, t }); + const origTags = Array.from(head.matchAll(/<([^>]+)>/g), (m) => m[1]); + let key: string | undefined; + if (origTags.includes('iv')) key = 'verb_iv'; + else if (origTags.includes('tv')) key = 'verb_tv'; + else if (origTags.some((tag) => tag.startsWith('v'))) key = 'vaux'; + else if (origTags.some((tag) => tag.startsWith('np.'))) key = 'pnoun'; + else if (origTags[0] === 'n') key = 'noun'; + if (!key) return []; + return blocksMap[key] || []; + }, + parseTags, +}; diff --git a/src/components/dictionary/types.ts b/src/components/dictionary/types.ts new file mode 100644 index 000000000..90d1896c7 --- /dev/null +++ b/src/components/dictionary/types.ts @@ -0,0 +1,33 @@ +import { CancelTokenSource } from 'axios'; + +export interface ParadigmCell { + tags?: string; + pretxt?: string; + text?: string; +} + +export interface ParadigmBlock { + id?: string; + label: () => string; + tabcols?: string[]; + tabrows?: string[]; + tabdata?: ParadigmCell[][]; + tablist?: Array<{ label: string; tags: string; pretxt?: string }>; + info?: string; + subcats?: ParadigmBlock[]; +} + +export interface AddParadigmsArgs { + head: string; + mode: string; + locale: string; + t: (key: string, vars?: any) => string; + apyFetch: (type: string, opts: any) => [CancelTokenSource, Promise]; +} + +export interface LanguagePlugin { + backendLangCode: string; + addParadigms: (args: AddParadigmsArgs) => ParadigmBlock[]; + parseTags: (origTags: string[], cellTags: string) => string[]; + getAvailableModes?: (locale: string) => string[]; +} diff --git a/src/components/navbar/index.tsx b/src/components/navbar/index.tsx index 51347cb76..10ca49bd4 100644 --- a/src/components/navbar/index.tsx +++ b/src/components/navbar/index.tsx @@ -107,6 +107,18 @@ const NavbarNav: React.ComponentType = (props: NavProps) => { )} + {enabledModes.has(Mode.Dictionary) && ( + + + pathname === '/dictionary' || (pathname === '/' && defaultMode === Mode.Dictionary) + } + to={'/dictionary'} + > + {t('Dictionary')} + + + )} ); }; diff --git a/src/strings/Makefile b/src/strings/Makefile index c21bbca6e..a83f9f761 100644 --- a/src/strings/Makefile +++ b/src/strings/Makefile @@ -1,6 +1,6 @@ all: cleanup update-readme -cleanup: $(shell find . -name '*.json' | egrep '/[a-z]{3}\.json') +cleanup: $(shell find . -name '*.json' -not -path './pos/*' | egrep '/[a-z]{3}\.json') ./localisation-tools.py cleanup $? update-readme: README.md diff --git a/src/strings/README.md b/src/strings/README.md index 272876975..0696b2da3 100644 --- a/src/strings/README.md +++ b/src/strings/README.md @@ -8,43 +8,44 @@ After editing localizations, please run `make` and commit its changes. | code | CBE* | CBC** | |------|------|-------| -| cat | 100% | 111.87% | -| sat | 100% | 108.75% | -| kaa | 100% | 103.90% | -| hin | 100% | 103.83% | -| skr | 100% | 101.22% | -| dan | 100% | 100.96% | -| nob | 100% | 100.82% | +| ukr | 100% | 100.91% | | eng | 100% | 100.00% | -| nno | 100% | 99.69% | -| deu | 97% | 113.72% | -| arg | 97% | 110.91% | -| fra | 97% | 109.78% | -| glg | 97% | 108.17% | -| frp | 97% | 107.22% | -| tat | 97% | 104.45% | -| tur | 97% | 103.25% | -| szl | 97% | 101.22% | -| mar | 97% | 100.60% | -| fin | 97% | 94.65% | -| ara | 97% | 90.09% | -| kir | 86% | 45.57% | -| srd | 82% | 90.82% | -| uzb | 80% | 91.22% | -| swe | 80% | 85.70% | -| rus | 80% | 81.71% | -| tha | 76% | 75.08% | -| spa | 71% | 26.86% | -| oci | 67% | 83.23% | -| uig | 67% | 77.88% | -| kaz | 67% | 77.17% | -| heb | 67% | 68.46% | -| sme | 56% | 14.70% | -| por | 49% | 12.32% | -| eus | 45% | 13.12% | -| ava | 43% | 12.47% | -| zho | 43% | 3.88% | -| ron | 39% | 9.02% | +| deu | 96% | 112.76% | +| arg | 88% | 108.32% | +| cat | 88% | 108.28% | +| sat | 88% | 105.26% | +| kaa | 88% | 100.56% | +| hin | 88% | 100.50% | +| skr | 88% | 97.97% | +| dan | 88% | 97.72% | +| nob | 88% | 97.59% | +| nno | 88% | 96.49% | +| fra | 84% | 106.25% | +| glg | 84% | 104.70% | +| frp | 84% | 103.77% | +| tat | 84% | 101.10% | +| tur | 84% | 99.94% | +| szl | 84% | 97.97% | +| mar | 84% | 97.37% | +| fin | 84% | 91.61% | +| ara | 84% | 87.20% | +| rus | 81% | 80.75% | +| kir | 75% | 44.10% | +| srd | 71% | 87.91% | +| uzb | 70% | 88.29% | +| swe | 70% | 82.95% | +| tha | 67% | 72.67% | +| spa | 62% | 26.00% | +| oci | 59% | 80.56% | +| uig | 59% | 75.38% | +| kaz | 59% | 74.69% | +| heb | 59% | 66.26% | +| sme | 49% | 14.23% | +| por | 42% | 11.92% | +| eus | 39% | 12.70% | +| ava | 38% | 12.07% | +| zho | 38% | 3.75% | +| ron | 34% | 8.73% | \*CBE: completion by entries
\**CBC: completion by characters (i.e., ratio of characters to English ~source) diff --git a/src/strings/ara.json b/src/strings/ara.json index 309092cbc..6f776b476 100644 --- a/src/strings/ara.json +++ b/src/strings/ara.json @@ -8,16 +8,23 @@ "ar", "ara" ], - "completion": " 97% 90.09%", + "completion": " 84% 87.20%", "missing": [ "Apertium_Documentation", - "Norm_Preferences" + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word" ] }, "title": " أبرتيُم | منصة ترجمة إلكترونية حرة ومفتوحة المصدر", "tagline": "منصََّة ترجمة إلكترونيَّة حُرَّة ومفتوحة المصدر", "description": "أبرتيُم هي منصة ترجمة إلكترونية تعنمد على القوانين اللغوية المُعدَّة مًسبقًا. أبرتيُم برمجية حُرَّة مُتاحة تحت رخصة غنو العامة..", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "ترجمة", "Translation_Help": "أدخل نصًّا أو رابطًا للترجمة.", "Translate": "ترجِم", @@ -57,7 +64,6 @@ "About": "عن", "Download": "تحميل", "Contact": "تواصُل", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "التوثيق", "About_Apertium": "حول أبرتُم", "What_Is_Apertium": "

أبرتيُم هي منصة ترجمة إلكترونية حرة ومفتوحة المصدر/b> بدأت كمنصة ترجمة إلكترونية للغات المتقاربة وتطورت لاحقا لتشمل لغات متباعدة أكثر (كالإنجليزية-الكتلانية). المنصة توفر

  1. محرك ترجمة إلكترونية مستقل
  2. أدوات لإدارة البيانات اللغوية الضرورية لإنشاء منصة ترجمة إلكترونية بين لغتين، و
  3. البيانات اللغوية لعدد متزايد من الأقران اللغوية.

أبرتيُم ترحب بالمطورين الجُدد: إن كنت ترى أن بإمكانك تطوير المحرك أو الأدوات، أو إنشاء وتطوير البيانات اللغوية للمنصة، فلا تتردد بتواصلوا معنا.

", diff --git a/src/strings/arg.json b/src/strings/arg.json index ac9232f39..7648a974c 100644 --- a/src/strings/arg.json +++ b/src/strings/arg.json @@ -8,8 +8,17 @@ "an", "arg" ], - "completion": " 100% 110.91%", - "missing": [] + "completion": " 88% 108.32%", + "missing": [ + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Search", + "Similar_To", + "Type_A_Word" + ] }, "title": "Apertium | Una plataforma libre de traducción automatica", "tagline": "Plataforma de traducción automatica libre/de codigo fuent ubierto", diff --git a/src/strings/ava.json b/src/strings/ava.json index 913b68cfc..b1aa7d785 100644 --- a/src/strings/ava.json +++ b/src/strings/ava.json @@ -8,66 +8,58 @@ "av", "ava" ], - "completion": " 43% 12.47%", + "completion": " 38% 12.07%", "missing": [ "About", "About_Apertium", "Apertium_Documentation", "Apertium_Downloads", "Cancel", + "Collapse_Paradigms", "Contact", "Contact_Para", + "Dictionary", "Documentation", "Documentation_Para", "Download", "Downloads_Para", "Drop_Document", "Enable_JS_Warning", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Install_Apertium", "Install_Apertium_Para", "Instant_Translation", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Available", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "What_Is_Apertium", "description" ] }, "title": "Апертиум | Машинияб таржамалъул эркенаб/рагьараб тӏагӏел", "tagline": "Машинияб таржамалъул эркенаб/рагьараб тӏагӏел", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Таржама", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Таржама гьабе", "Detect_Language": "Мацӏ батӏа бахъизабе", "detected": "батӏа бахъизабун буго", - "Instant_Translation": "%%UNAVAILABLE%% Instant translation", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", - "Not_Available": "%%UNAVAILABLE%% Translation not yet available!", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", - "Cancel": "%%UNAVAILABLE%% Cancel", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Морфологияб анализ", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Анализ гьабе", "Morphological_Generation": "Морфологияб синтез", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Синтез гьабе", "Spell_Checker": "Битӏунхъваялъул хал-шал", "APy_Sandbox": "APy расанизари", @@ -80,20 +72,5 @@ "Help_Improve": "Апертиум лъиклъизе кумек гьабе!", "Contact_Us": "Гьара-рахьи ратани, гъалатӏ батун батани яги кумек гьабизе бокьун батани, хъвай нижехе.", "Maintainer": "Гьаб сайталъул кверчӏвай ва тадбир гьабулеб буго {{maintainer}}.", - "About_Title": "Гьаб сайталъул хӏакъалъулъ", - "Enable_JS_Warning": "%%UNAVAILABLE%% This site only works with JavaScript enabled, if you cannot enable Javascript, then try the translators at Prompsit.", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", - "About": "%%UNAVAILABLE%% About", - "Download": "%%UNAVAILABLE%% Download", - "Contact": "%%UNAVAILABLE%% Contact", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", - "Documentation": "%%UNAVAILABLE%% Documentation", - "About_Apertium": "%%UNAVAILABLE%% About Apertium", - "What_Is_Apertium": "%%UNAVAILABLE%%

Apertium is a free/open-source machine translation platform, initially aimed at related-language pairs but expanded to deal with more divergent language pairs (such as English-Catalan). The platform provides

  1. a language-independent machine translation engine
  2. tools to manage the linguistic data necessary to build a machine translation system for a given language pair and
  3. linguistic data for a growing number of language pairs.

Apertium welcomes new developers: if you think you can improve the engine or the tools, or develop linguistic data for us, do not hesitate to contact us.

", - "Documentation_Para": "%%UNAVAILABLE%% Documentation can be found on our Wiki under the Documentation sub-page. We have published various conference papers and journal articles, a list of which may be found on the Wiki under Publications.", - "Apertium_Downloads": "%%UNAVAILABLE%% Apertium Downloads", - "Downloads_Para": "%%UNAVAILABLE%% Current versions of the Apertium toolbox as well as of language-pair data are available from the GitHub page. Installation instructions for Apertium on all major platforms are provided on the Wiki's Installation page.", - "Contact_Para": "%%UNAVAILABLE%%

IRC channel

The quickest way to contact us is by joining our IRC channel, #apertium at irc.oftc.net, where users and developers of Apertium meet. You don't need an IRC client; you can use OFTC webchat.

Mailing list

Also, subscribe to the apertium-stuff mailing list, where you can post longer proposals or issues, as well as follow general Apertium discussions.

Contact

Feel free to contact us via the apertium-contact mailing list if you find a mistake, there's a project you would like to see us work on, or you would like to help out.

", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "About_Title": "Гьаб сайталъул хӏакъалъулъ" } diff --git a/src/strings/cat.json b/src/strings/cat.json index 14eb3ce0e..91b86aeba 100644 --- a/src/strings/cat.json +++ b/src/strings/cat.json @@ -10,8 +10,17 @@ "ca", "cat" ], - "completion": "100% 111.87%", - "missing": [] + "completion": " 88% 108.28%", + "missing": [ + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Search", + "Similar_To", + "Type_A_Word" + ] }, "title": "Apertium | Una plataforma lliure per a la traducció automàtica", "tagline": "Plataforma lliure i de codi obert per a la traducció automàtica", diff --git a/src/strings/dan.json b/src/strings/dan.json index 58af4158e..b255f05eb 100644 --- a/src/strings/dan.json +++ b/src/strings/dan.json @@ -8,8 +8,17 @@ "da", "dan" ], - "completion": "100% 100.96%", - "missing": [] + "completion": " 88% 97.72%", + "missing": [ + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Search", + "Similar_To", + "Type_A_Word" + ] }, "title": "Apertium | En fri/open source maskinoversættelsesplatform", "tagline": "En fri/open source maskinoversættelsesplatform", diff --git a/src/strings/deu.json b/src/strings/deu.json index 54a700de5..3b8f93e6c 100644 --- a/src/strings/deu.json +++ b/src/strings/deu.json @@ -8,16 +8,16 @@ "de", "deu" ], - "completion": " 97% 113.72%", + "completion": " 96% 112.76%", "missing": [ "Apertium_Documentation", + "More_Languages", "Norm_Preferences" ] }, "title": "Apertium | Eine freie/quelloffene Plattform für maschinelle Übersetzungen", "tagline": "Eine freie/quelloffene Plattform für maschinelle Übersetzungen", "description": "Apertium ist eine Plattform für regelbasierte maschinelle Übersetzungen. Es ist freie Software und wurde unter den Bedingungen der GNU General Public License veröffentlicht.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Übersetzung", "Translation_Help": "Geben Sie den zu übersetzenden Text bzw. die zu übersetzende URL ein.", "Translate": "Übersetzen", @@ -57,7 +57,6 @@ "About": "Über", "Download": "Herunterladen", "Contact": "Kontakt", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Dokumentation", "About_Apertium": "Über Apertium", "What_Is_Apertium": "

Apertium ist eine freie/quelloffene Plattform für maschinelle Übersetzungen, zielte ursprünglich auf Paare verwandter Sprachen ab, wurde aber erweitert, um mit divergenteren Sprachpaaren arbeiten zu können (wie z.B. Englisch-Katalanisch). Die Plattform bietet

  1. eine Sprachunabhängige Engine für maschinelle Übersetzungen
  2. Werkzeuge um die linguistischen Daten zu verwalten, die für den Bau eines Systems für maschinelle Übersetzungen für ein gegebenes Sprachpaar nötig sind und
  3. linguistische Daten für eine wachsende Anzahl von Sprachpaaren.

Apertium begrüßt neue Entwickler: Wenn Sie glauben, dass Sie die Engine verbessern oder linguistische Daten für uns entwickeln können, zögern Sie nicht uns zu kontaktieren.

", @@ -66,5 +65,12 @@ "Downloads_Para": "Aktuelle Versionen der Apertium-Toolbox sowie der Sprachpaar-Daten können von der GitHub-Seite sf.net/projects/apertium bezogen werden. Installationsanweisungen für Apertium auf allen größeren Plattformen werden auf der Installationsseite des Wikis bereitgestellt.", "Contact_Para": "

IRC-Kanal

Der schnellste Weg, mit uns Kontakt aufzunehmen, ist, unserem IRC-Kanal, #apertium bei irc.oftc.net beizutreten, wo sich Benutzer und Entwickler von Apertium treffen. Sie brauchen keinen IRC-Client; Sie können OFTC webchat benutzen.

Mailingliste

Abonnieren Sie auch die apertium-stuff-Mailingliste, an die Sie längere Vorschläge oder Probleme schicken und auch der allgemeinen Apertium-Diskussion folgen können.

Kontakt

Gerne können Sie uns über die apertium-contact-Mailingliste kontaktieren, wenn Sie einen Fehler finden, es ein Projekt gibt, an dem Sie uns gerne arbeiten sehen würden, oder Sie aushelfen möchten.

", "Install_Apertium": "Apertium installieren", - "Install_Apertium_Para": "Erleben Sie lange Antwortzeiten? Unsere Server sind möglicherweise überlastet. Lernen Sie Apertium lokal zu installieren." + "Install_Apertium_Para": "Erleben Sie lange Antwortzeiten? Unsere Server sind möglicherweise überlastet. Lernen Sie Apertium lokal zu installieren.", + "Dictionary": "Wörterbuch", + "Type_A_Word": "Geben Sie ein Wort zur Suche ein", + "Search": "Suche", + "No_results_found": "Keine Ergebnisse gefunden!", + "Expand_Paradigms": "Paradigmen erweitern", + "Collapse_Paradigms": "Paradigmen einklappen", + "Similar_To": "ähnlich wie" } diff --git a/src/strings/eng.json b/src/strings/eng.json index cc7d6a706..3c365c5b2 100644 --- a/src/strings/eng.json +++ b/src/strings/eng.json @@ -64,5 +64,12 @@ "Downloads_Para": "Current versions of the Apertium toolbox as well as of language-pair data are available from the GitHub page. Installation instructions for Apertium on all major platforms are provided on the Wiki's Installation page.", "Contact_Para": "

IRC channel

The quickest way to contact us is by joining our IRC channel, #apertium at irc.oftc.net, where users and developers of Apertium meet. You don't need an IRC client; you can use OFTC webchat.

Mailing list

Also, subscribe to the apertium-stuff mailing list, where you can post longer proposals or issues, as well as follow general Apertium discussions.

Contact

Feel free to contact us via the apertium-contact mailing list if you find a mistake, there's a project you would like to see us work on, or you would like to help out.

", "Install_Apertium": "Install Apertium", - "Install_Apertium_Para": "Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Install_Apertium_Para": "Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally.", + "Dictionary": "Dictionary", + "Type_A_Word": "Type a word to search", + "Search": "Search", + "No_results_found": "No results found!", + "Expand_Paradigms": "Expand paradigms", + "Collapse_Paradigms": "Collapse Paradigms", + "Similar_To": "similar to" } diff --git a/src/strings/eus.json b/src/strings/eus.json index cba6201f0..08301db76 100644 --- a/src/strings/eus.json +++ b/src/strings/eus.json @@ -5,65 +5,58 @@ "locale": [ "eus" ], - "completion": " 45% 13.12%", + "completion": " 39% 12.70%", "missing": [ "About", "About_Apertium", "Apertium_Documentation", "Apertium_Downloads", "Cancel", + "Collapse_Paradigms", "Contact", "Contact_Para", + "Dictionary", "Documentation", "Documentation_Para", "Download", "Downloads_Para", "Drop_Document", "Enable_JS_Warning", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Install_Apertium", "Install_Apertium_Para", "Instant_Translation", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "What_Is_Apertium", "description" ] }, "title": "Apertium | Kode irekiko itzulpen automatiko plataforma librea", "tagline": "Kode irekiko itzulpen automatiko plataforma librea", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Itzulpena", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Itzuli", "Detect_Language": "Hizkuntza detektatu", "detected": "detektatua", - "Instant_Translation": "%%UNAVAILABLE%% Instant translation", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "Itzulpena ez dago oraindik eskuragarri!", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", - "Cancel": "%%UNAVAILABLE%% Cancel", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Analisi morfologikoa", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Analizatu", "Morphological_Generation": "Sorkuntza morfologikoa", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Sorkuntza", "Spell_Checker": "Zuzentzaile ortografikoa", "APy_Sandbox": "APy Sandbox", @@ -76,20 +69,5 @@ "Help_Improve": "Lagun iezaiguzu Apertium hobetzen!", "Contact_Us": "Akats bat bilatzemn baduzu, proiektu bat guk lantzea nahi baduzu, edo lagundu nahi ba diguzu, kontakta gaitzazu.", "Maintainer": "Webgune hau {{maintainer}}-ek mantentzen du.", - "About_Title": "Webgune honetaz", - "Enable_JS_Warning": "%%UNAVAILABLE%% This site only works with JavaScript enabled, if you cannot enable Javascript, then try the translators at Prompsit.", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", - "About": "%%UNAVAILABLE%% About", - "Download": "%%UNAVAILABLE%% Download", - "Contact": "%%UNAVAILABLE%% Contact", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", - "Documentation": "%%UNAVAILABLE%% Documentation", - "About_Apertium": "%%UNAVAILABLE%% About Apertium", - "What_Is_Apertium": "%%UNAVAILABLE%%

Apertium is a free/open-source machine translation platform, initially aimed at related-language pairs but expanded to deal with more divergent language pairs (such as English-Catalan). The platform provides

  1. a language-independent machine translation engine
  2. tools to manage the linguistic data necessary to build a machine translation system for a given language pair and
  3. linguistic data for a growing number of language pairs.

Apertium welcomes new developers: if you think you can improve the engine or the tools, or develop linguistic data for us, do not hesitate to contact us.

", - "Documentation_Para": "%%UNAVAILABLE%% Documentation can be found on our Wiki under the Documentation sub-page. We have published various conference papers and journal articles, a list of which may be found on the Wiki under Publications.", - "Apertium_Downloads": "%%UNAVAILABLE%% Apertium Downloads", - "Downloads_Para": "%%UNAVAILABLE%% Current versions of the Apertium toolbox as well as of language-pair data are available from the GitHub page. Installation instructions for Apertium on all major platforms are provided on the Wiki's Installation page.", - "Contact_Para": "%%UNAVAILABLE%%

IRC channel

The quickest way to contact us is by joining our IRC channel, #apertium at irc.oftc.net, where users and developers of Apertium meet. You don't need an IRC client; you can use OFTC webchat.

Mailing list

Also, subscribe to the apertium-stuff mailing list, where you can post longer proposals or issues, as well as follow general Apertium discussions.

Contact

Feel free to contact us via the apertium-contact mailing list if you find a mistake, there's a project you would like to see us work on, or you would like to help out.

", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "About_Title": "Webgune honetaz" } diff --git a/src/strings/fin.json b/src/strings/fin.json index 67dcef9a3..49508ac69 100644 --- a/src/strings/fin.json +++ b/src/strings/fin.json @@ -9,16 +9,23 @@ "fi", "fin" ], - "completion": " 97% 94.65%", + "completion": " 84% 91.61%", "missing": [ "Apertium_Documentation", - "Norm_Preferences" + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word" ] }, "title": "Apertium – Vapaa konekäännösalusta", "tagline": "Vapaa avoimen lähdekoodin konekäännösalusta", "description": "Apertium on sääntöpohjainen konekäännösalusta. Se on vapaata lähdekoodia ja julkaistu GNU:N GPL-lisenssillä.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Käännös", "Translation_Help": "Kirjoita tekstiä tai verkko-osoite käännettäväksi.", "Translate": "Käännä", @@ -58,7 +65,6 @@ "About": "Tietoja", "Download": "Lataa", "Contact": "Yhteystiedot", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Ohjeet", "About_Apertium": "Tietoja Apertiumista", "What_Is_Apertium": "

Apertium on vapaa avoimen lähdekoodin konekäännösalusta. Alunperin Apertium tehtiin lähisukukielien käännökseen, mutta sitä on myöhemmin laajennettu etäisemmille kielipareille (esim. englanti-katalaani). Alusta sisältää:

  1. kieliriippumattoman konekäännösenginen
  2. työkaluja sellaisen lingvistisen datan hallintaan jota tarvitaan konekäännöksessä, ja
  3. lingvististä dataa kasvavalle joukolle kieliä

Apertium kannustaa uusien kehittäjien osanottoa, jos voit auttaa enginen tai työkalujen kehityksessä tai kerryttää lingvististä dataa, voit lähettää viestin meille.

", diff --git a/src/strings/fra.json b/src/strings/fra.json index 53f862640..ecde40488 100644 --- a/src/strings/fra.json +++ b/src/strings/fra.json @@ -11,16 +11,23 @@ "fr", "fra" ], - "completion": " 97% 109.78%", + "completion": " 84% 106.25%", "missing": [ "Apertium_Documentation", - "Norm_Preferences" + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word" ] }, "title": "Apertium | Une plateforme libre/open source de traduction automatique", "tagline": "Une plateforme libre/open source de traduction automatique", "description": "Apertium est une plateforme de traduction automatique basée sur des règles. C'est un logiciel libre distribué selon les termes de la licence GNU GPL.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Traduction", "Translation_Help": "Entrez un texte ou un URL pour le traduire.", "Translate": "Traduire", @@ -60,7 +67,6 @@ "About": "À propos", "Download": "Télécharger", "Contact": "Contact", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Documentation", "About_Apertium": "À propos d'Apertium", "What_Is_Apertium": "

Apertium est une plateforme de traduction automatique libre/open source, conçue à l'origine pour des paires de langues proches, puis s'est étendue à des paires de langues plus éloignées comme la paire anglais-catalan. La plateforme fournit :

  1. un moteur de traduction automatique qui ne dépend pas d'une quelconque langue
  2. des outils linguistiques pour gérer les données nécessaires à la réalisation d'un système de traduction automatique pour une paire de langues donnée
  3. des données linguistiques pour un nombre croissant de paires de langues.

Apertium apprécie l'arrivée de nouveaux développeurs : si vous estimez que vous pouvez améliorez le moteur, les outils ou les données linguistiques, n'hésitez pas à prendre contact avec nous.

", diff --git a/src/strings/frp.json b/src/strings/frp.json index 37fb43b4b..f57847b77 100644 --- a/src/strings/frp.json +++ b/src/strings/frp.json @@ -8,16 +8,23 @@ "locale": [ "frp" ], - "completion": " 97% 107.22%", + "completion": " 84% 103.77%", "missing": [ "Apertium_Documentation", - "Norm_Preferences" + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word" ] }, "title": "Apertium | Una plataforma libra/a codo-sôrsa uvèrt de traduccion ôtomatica", "tagline": "Una plataforma libra/a codo-sôrsa uvèrt de traduccion ôtomatica", "description": "Apertium est una plataforma de traduccion ôtomatica fondâye sur des règlles. O est una programerie libra distribuâye d'aprés los tèrmenos de la licence GNU GPL.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Traduccion", "Translation_Help": "Enfatar un tèxto ou un URL por lo traduire.", "Translate": "Traduire", @@ -57,7 +64,6 @@ "About": "A propôs", "Download": "Tèlèchargiér", "Contact": "Contacto", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Documentacion", "About_Apertium": "A propôs d'Apertium", "What_Is_Apertium": "

Apertium est una plataforma de traduccion ôtomatica libra/a codo-sôrsa uvèrt, conçua a l'origina por des cobles de lengoues vesenes, pués s'est ètèrsa a des cobles de lengoues més luentênes coment la cobla anglês-catalan. La plataforma balye :

  1. un motor de traduccion ôtomatica que dèpend pas d'una cèrtêna lengoua
  2. des outils lengouisticos por maneyér les donâs nècèssères a la rèalisacion d'un sistèmo de traduccion ôtomatica por una cobla de lengoues donâye
  3. des donâs lengouistiques por un nombro crèssent de cobles de lengoues.

Apertium aprèciye l'arrevâ de novéls dèvelopors : se vos trovâd que vous pouede mèlyorar lo motor, los outils ou les donâs lengouistiques, fôt pas margalyér a nos contactar.

", diff --git a/src/strings/glg.json b/src/strings/glg.json index 7f3081933..e0eb02444 100644 --- a/src/strings/glg.json +++ b/src/strings/glg.json @@ -9,16 +9,23 @@ "gl", "glg" ], - "completion": " 97% 108.17%", + "completion": " 84% 104.70%", "missing": [ "Apertium_Documentation", - "Norm_Preferences" + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word" ] }, "title": "Apertium | Unha plataforma libre e de código aberto para a tradución automática", "tagline": "Unha plataforma libre e de código aberto para a tradución automática", "description": "Apertium é unha plataforma de tradución automática baseada en regras. É un programa libre que se publica baixo os termos da licenza GPL (GNU General Public License).", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Tradución", "Translation_Help": "Escriba o texto ou o URL a traducir.", "Translate": "Traducir", @@ -58,7 +65,6 @@ "About": "Sobre", "Download": "Descargar", "Contact": "Contacto", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Documentación", "About_Apertium": "Sobre Apertium", "What_Is_Apertium": "

Apertium é unha plataforma libre e de código aberto para a tradución automática, inicialmente concibida para a tradución entre parellas de idiomas relacionados pero estendeuse para tratar con parellas de idiomas máis diferentes (tales como Inglés-Catalán). A plataforma fornece

  1. un motor de tradución independente do idioma
  2. ferramentas para xestionar os datos lingüísticos necesarios para construír un sistema de tradución automático para unha determinada parella de idiomas
  3. datos lingüísticos para unha cantidade de parellas de idiomas cada vez máis grande.

Apertium dálle a benvida a novos desenvolvedores: se pensa que pode mellorar o motor ou as ferramentas, ou desenvolver datos lingüísticos para nós, non dúbide contactar connosco.

", diff --git a/src/strings/heb.json b/src/strings/heb.json index 20f95cb85..48f779815 100644 --- a/src/strings/heb.json +++ b/src/strings/heb.json @@ -8,53 +8,47 @@ "he", "heb" ], - "completion": " 67% 68.46%", + "completion": " 59% 66.26%", "missing": [ "Apertium_Documentation", "Cancel", + "Collapse_Paradigms", + "Dictionary", "Drop_Document", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Install_Apertium", "Install_Apertium_Para", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "description" ] }, "title": "Apertium | פלטפורמה חופשית לתרגום מכונה", "tagline": "פלטפורמה חופשית לתרגום מכונה", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "תרגום", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "תרגם", "Detect_Language": "זהה שפה", "detected": "זוהתה", "Instant_Translation": "מיידי", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "התרגום עוד לא זמין!", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", - "Cancel": "%%UNAVAILABLE%% Cancel", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "ניתוח מורפולוגי", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "נתח", "Morphological_Generation": "חילול מורפולוגי", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "חולל", "Spell_Checker": "בודק איות", "APy_Sandbox": "ארגז כלים ל-APy", @@ -69,18 +63,14 @@ "Maintainer": "אתר זה מתוחזק ע\"י {{maintainer}}.", "About_Title": "אודות אתר זה", "Enable_JS_Warning": "אתר זה פועל רק כש-Javascript מופעלת, אם אין באפשרותכם להפעיל את Javacript, תוכלו לנסות את כלי התרגום ב-Prompsit.", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", "About": "אודות", "Download": "הורד", "Contact": "צור קשר", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "תיעוד", "About_Apertium": "אודות Apertium", "What_Is_Apertium": "

Apertium היא פלטפורמה חופשית לתרגום מכונה, שנועדה במקור לתרגום בין זוגות של שפות קשורות אך הורחבה לטפל גם בזוגות של שפות רחוקות יותר (כמו אנגלית-קטלאנית). הפלטפורמה מספקת

  1. מנוע תרגום מכונה ללא תלות בשפה מסוימת
  2. כלים לניהול המידע הבלשני הדרוש לבניית מערכת תרגום מכונה עבור זוג מסוים של שפות, ו
  3. מידע בלשני עבור מספר הולך וגדל של זוגות של שפות.

Apertium מקבלת בברכה מפתחים חדשים: אם לדעתכם תוכלו לשפר את המנוע או את הכלים בפרויקט, או לפתח מידע בלשני עבורנו, אל תהססו לפנות אלינו.

", "Documentation_Para": "תיעוד ניתן למצוא ב-Wiki שלנו תחת הדף Documentation. כמו כן, פרסמנו מאמרים שונים במסגרת כנסים אקדמיים וכתבי עת, תוכלו למצוא רשימה של אלו ב-Wiki תחת Publications.", "Apertium_Downloads": "הורדות Apertium", "Downloads_Para": " הגרסאות האחרונות של ארגז הכלים של Apertium, כמו גם מידע עבור זוגות שפות זמינים לעיון והורדה בדף הפרויקט ב-GitHub. הוראות ההתקנה של Apertium עבור עיקר הפלטפורמות מפורטות בדף ההתקנה ב-Wiki.", - "Contact_Para": "

ערוץ IRC

הדרך הזריזה ביותר לפנות אלינו היא בהצטרפות לערוץ ה-IRC שלנו, #apertium ב-irc.oftc.net, בו נפגשים המשתמשים והמפתחים של Apertium. אין צורך בתוכנה מיוחדת; ניתן להשתמש ב-OFTC webchat.

רשימת דיוור

כמו כן, תוכלו להירשם לרשימת הדיוור apertium-stuff, שם תוכלו לכתוב בפירוט לגבי הצעות או בעיות, כמו גם לעקוב אחר דיונים כלליים בנושא Apertium.

יצירת קשר

הרגישו חופשי ליצור קשר באמצעות רשימת הדיוור apertium-contact אם מצאתם טעות, יש פרויקט שתרצו לראות אותנו עובדים עליו, או שאתם מעוניינים להציע עזרה.

", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Contact_Para": "

ערוץ IRC

הדרך הזריזה ביותר לפנות אלינו היא בהצטרפות לערוץ ה-IRC שלנו, #apertium ב-irc.oftc.net, בו נפגשים המשתמשים והמפתחים של Apertium. אין צורך בתוכנה מיוחדת; ניתן להשתמש ב-OFTC webchat.

רשימת דיוור

כמו כן, תוכלו להירשם לרשימת הדיוור apertium-stuff, שם תוכלו לכתוב בפירוט לגבי הצעות או בעיות, כמו גם לעקוב אחר דיונים כלליים בנושא Apertium.

יצירת קשר

הרגישו חופשי ליצור קשר באמצעות רשימת הדיוור apertium-contact אם מצאתם טעות, יש פרויקט שתרצו לראות אותנו עובדים עליו, או שאתם מעוניינים להציע עזרה.

" } diff --git a/src/strings/hin.json b/src/strings/hin.json index 037debba6..66dbacd12 100644 --- a/src/strings/hin.json +++ b/src/strings/hin.json @@ -8,8 +8,17 @@ "hi", "hin" ], - "completion": "100% 103.83%", - "missing": [] + "completion": " 88% 100.50%", + "missing": [ + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Search", + "Similar_To", + "Type_A_Word" + ] }, "title": "Apertium | एक मुक्त/खुला - स्रोत मशीनी अनुवाद प्लेटफाँर्म ।", "tagline": "एक मुक्त/खुला - स्रोत स्रोत मशीनी अनुवाद प्लेटफाँर्म", diff --git a/src/strings/kaa.json b/src/strings/kaa.json index 53219eaf5..3913c5211 100644 --- a/src/strings/kaa.json +++ b/src/strings/kaa.json @@ -8,8 +8,17 @@ "locale": [ "kaa" ], - "completion": "100% 103.90%", - "missing": [] + "completion": " 88% 100.56%", + "missing": [ + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Search", + "Similar_To", + "Type_A_Word" + ] }, "title": "Apertium | Biypul/ashıq mashinalı awdarmalaw platforması", "tagline": "Biypul/ashıq mashinalı awdarmalaw platforması", diff --git a/src/strings/kaz.json b/src/strings/kaz.json index dcfb0b9db..9fe23a48f 100644 --- a/src/strings/kaz.json +++ b/src/strings/kaz.json @@ -9,53 +9,47 @@ "kk", "kaz" ], - "completion": " 67% 77.17%", + "completion": " 59% 74.69%", "missing": [ "Apertium_Documentation", "Cancel", + "Collapse_Paradigms", + "Dictionary", "Drop_Document", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Install_Apertium", "Install_Apertium_Para", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "description" ] }, "title": "Apertium | A free/open-source machine translation platform", "tagline": "A free/open-source machine translation platform", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Аударма", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Аудару", "Detect_Language": "Тілді анықтау", "detected": "анықталды", "Instant_Translation": "Шапшаң аударма", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "Аударма әзірше қолжетімді емес", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", - "Cancel": "%%UNAVAILABLE%% Cancel", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Морфологиялық анализ", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Талдау", "Morphological_Generation": "Морфологиялық синтез", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Синтездеу", "Spell_Checker": "Емлені тексергіш", "APy_Sandbox": "APy құмжәшік", @@ -70,18 +64,14 @@ "Maintainer": "Осы веб-сайтты {{maintainer}} сүйемелдейді.", "About_Title": "Бұл веб-сайт туралы", "Enable_JS_Warning": "Осы сайт тек қана қосулы JavaScript жұмыс жасайды, егер сізде жоқ болса enable Javascript, одан кейін орындаңыз translators at Prompsit.", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", "About": "Жоба туралы", "Download": "Жүктеп алу", "Contact": "Байланыс", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Құжаттама", "About_Apertium": "Апертиум туралы", "What_Is_Apertium": "

Apertium бұл тегін/ашық-дереккөзді машиналық аударма платформасы, алғашқы кезде байланысқан тілдік жұптар үшін болған, бірақ, кейін көбірек ауытқыған тілдік жұптар(Ағылшын-Каталан сияқты) үшін кеңейтілген болатын. Платформа құралады

  1. тілдік-тәуелсіз машиналық аударма қозғалтқышынан
  2. берілген тілдік жұбының машиналық аударма жүйесін құру үшін қажетті лингвистикалық қорды басқаратын құралдардан

      Апертиум жаңа құрушыларды күтеді: егер сізде қозғалтқышты немесе құралдарды жетілдіру ойыңыз болса немесе бізге лингвистикалық қорды дамыта алсаңыз, онда көп ойламай арқылы бізбен хабарласыңыз.

      ", "Documentation_Para": "Құжаттама біздің Wiki сайтының Құжаттама ішкі бетінде таба аласыз. Біз әр түрлі баяндамалар мен журнал мақалаларын шығардық, олардың тізімін Wiki сайтында Басылымдар бөлімінде таба аласыз.", "Apertium_Downloads": "Апертиумды жүктеп алу", "Downloads_Para": "Ағымдағы Апертиум құралдарын сондай-ақ тілдік-жұп деректерін GitHub бетінде таба аласыз. Апертиумды негізгі платформаларға орнату үшін нұсқаулықтар Wiki-ның орнату бетінде көрсетілген.", - "Contact_Para": "

      IRC channel

      Байланысудың ең тез жолы - біздің IRC арнамызға, #apertium irc.oftc.net сайтында қосылу, бұл жерде Апертиумның қолданушылары мен құраушылары кездеседі. Сізге IRC client қажет емес; қолдану үшін OFTC webchat қосылыңыз.

      Жіберу тізімі

      Сонымен қатар, apertium-stuff mailing list жазылыңыз, бұл жерде сіз ұзынырақ сұраныстар мен мәселелерді жібере аласыз, Апертиумның жалпы талқылауларда сияқты.

      Байланысу

      Бізбен жеңіл хабарласыңыз aпертиум-байланыс жіберу тізімі арқылы, әсіресе, егер сіз біз жасап жатқан жобада қате тапсаңыз немесе осы жобаға көмектескіңіз келсе.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Contact_Para": "

      IRC channel

      Байланысудың ең тез жолы - біздің IRC арнамызға, #apertium irc.oftc.net сайтында қосылу, бұл жерде Апертиумның қолданушылары мен құраушылары кездеседі. Сізге IRC client қажет емес; қолдану үшін OFTC webchat қосылыңыз.

      Жіберу тізімі

      Сонымен қатар, apertium-stuff mailing list жазылыңыз, бұл жерде сіз ұзынырақ сұраныстар мен мәселелерді жібере аласыз, Апертиумның жалпы талқылауларда сияқты.

      Байланысу

      Бізбен жеңіл хабарласыңыз aпертиум-байланыс жіберу тізімі арқылы, әсіресе, егер сіз біз жасап жатқан жобада қате тапсаңыз немесе осы жобаға көмектескіңіз келсе.

      " } diff --git a/src/strings/kir.json b/src/strings/kir.json index a085352d8..b4b49bd56 100644 --- a/src/strings/kir.json +++ b/src/strings/kir.json @@ -9,22 +9,29 @@ "ky", "kir" ], - "completion": " 86% 45.57%", + "completion": " 75% 44.10%", "missing": [ "Apertium_Documentation", + "Collapse_Paradigms", "Contact_Para", + "Dictionary", "Downloads_Para", + "Expand_Paradigms", "Install_Apertium_Para", + "More_Languages", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word", "What_Is_Apertium" ] }, "title": "Apertium | Эркин/ачык машинелик котормо платформасы", "tagline": "Эркин/ачык машинелик котормо платформасы", "description": "Апертиум деген эрежелүү машинелик котормо флатформасы. Apertium is a rule-based machine translation platform. Ал эркин жана ачык софт, жана GNU GPL жалпы ачык лицензиясынын шарттары боюнча камсыздалат.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Которуу", "Translation_Help": "Текст же URL киргизиңиз.", "Translate": "Котор", @@ -32,7 +39,6 @@ "detected": "автоматтык түрдө аныкталды", "Instant_Translation": "Ыкчам которуу", "Mark_Unknown_Words": "Билбеген сөздөрдү белгилөө", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", "Translate_Document": "Документ которуу", "Drop_Document": "Документ бул жерге ташыңыз", "Not_Available": "Котормо даяр эмес", @@ -45,7 +51,6 @@ "Morphological_Analysis_Help": "Синтездөгүңүз келген сөзформалар киргизиңиз.", "Analyze": "Талдоо", "Morphological_Generation": "Морфологиялык синтездөө", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Синтездөө", "Spell_Checker": "Катаны текшерүү", "APy_Sandbox": "APy кум аянтчасы", @@ -64,14 +69,9 @@ "About": "Проект жөнүндө", "Download": "Жүктөп алуу", "Contact": "Байланышуу", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Документация", "About_Apertium": "Апертиум жөнүндө", - "What_Is_Apertium": "%%UNAVAILABLE%%

      Apertium is a free/open-source machine translation platform, initially aimed at related-language pairs but expanded to deal with more divergent language pairs (such as English-Catalan). The platform provides

      1. a language-independent machine translation engine
      2. tools to manage the linguistic data necessary to build a machine translation system for a given language pair and
      3. linguistic data for a growing number of language pairs.

      Apertium welcomes new developers: if you think you can improve the engine or the tools, or develop linguistic data for us, do not hesitate to contact us.

      ", "Documentation_Para": "Документация викибиздеги Документция барагында табылат. Биз айрым презентация жана илимий баяндама басып чыгарганбыз. Алардын тизмеси викинин Чыгармалар барагында табылат.", "Apertium_Downloads": "Апертиумду жүктөп алуу", - "Downloads_Para": "%%UNAVAILABLE%% Current versions of the Apertium toolbox as well as of language-pair data are available from the GitHub page. Installation instructions for Apertium on all major platforms are provided on the Wiki's Installation page.", - "Contact_Para": "%%UNAVAILABLE%%

      IRC channel

      The quickest way to contact us is by joining our IRC channel, #apertium at irc.oftc.net, where users and developers of Apertium meet. You don't need an IRC client; you can use OFTC webchat.

      Mailing list

      Also, subscribe to the apertium-stuff mailing list, where you can post longer proposals or issues, as well as follow general Apertium discussions.

      Contact

      Feel free to contact us via the apertium-contact mailing list if you find a mistake, there's a project you would like to see us work on, or you would like to help out.

      ", - "Install_Apertium": "Апертиумду орнотуу", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Install_Apertium": "Апертиумду орнотуу" } diff --git a/src/strings/locales.json b/src/strings/locales.json index 32eaf3594..8c2e868dd 100644 --- a/src/strings/locales.json +++ b/src/strings/locales.json @@ -33,6 +33,7 @@ "tat": "татарча", "tur": "Türkçe", "uig": "ئۇيغۇرچە", + "ukr": "українська", "uzb": "oʻzbekcha", "zho": "汉语" } diff --git a/src/strings/mar.json b/src/strings/mar.json index 83dc4eeea..48be07629 100644 --- a/src/strings/mar.json +++ b/src/strings/mar.json @@ -8,16 +8,23 @@ "mr", "mar" ], - "completion": " 97% 100.60%", + "completion": " 84% 97.37%", "missing": [ "Apertium_Documentation", - "Norm_Preferences" + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word" ] }, "title": "अपर्टियम | मुक्त/ओपन-सोर्स संगणकीय भाषांतराच्या साधनांचा समूह", "tagline": "मुक्त/ओपन-सोर्स संगणकीय भाषांतराच्या साधनांचा समूह", "description": "अपर्टियम हा नियमबद्ध संगणकीय भाषांतराच्या साधनांचा समूह आहे. ही मुक्त (फ्री) साधने 'ग्नू जेनरल पब्लिक लायसन्स' या परवान्यासहित पुरवली आहेत.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "भाषांतर", "Translation_Help": "भाषांतरासाठी शब्द, वाक्ये, किंवा यू.आर.एल. लिहा.", "Translate": "भाषांतर करा", @@ -57,7 +64,6 @@ "About": "माहिती", "Download": "डाऊनलोड", "Contact": "संपर्क", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "तांत्रिक निर्देश", "About_Apertium": "अपर्टियम बद्दल माहिती", "What_Is_Apertium": "

      अपर्टियम हा मुक्त/ओपन-सोर्स संगणकीय भाषांतराच्या साधनांचा समूह आहे. पूर्वी ही साधने फक्त् जवळचे संबंध असलेल्या भाषांसाठी उपयुक्त होती, पण ती आता इतर भाषांमधल्या भाषांतरासाठीही वापरली जाऊ शकतात, जसे की इंग्रजी-कॅटलान. ही साधने नेमकी कोणती?

      1. कोणत्याही भाषांसाठी उपयुक्त भाषांतराचे सॉफ्टवेअर इंजिन;
      2. ह्या इंजिनसाठी आवश्यक असलेला प्रत्येक भाषेचा डेटा: शब्दकोश, नियमावल्या, इ.; आणि
      3. ह्या सगळ्याचे संचलन करण्यासाठी व ते उपयोगात आणण्यासाठी सॉफ्टवेअर साधने.

      अपर्टियम मध्ये नवीन डेव्हलपर्सचे नेहमी स्वागत असते: तुम्हाला जर ही साधने किंवा हा भाषांचा डेटा सुधारण्यात मदत करायची असेल, तर आमच्याशी जरूर संपर्क साधा.

      ", diff --git a/src/strings/nno.json b/src/strings/nno.json index 8e0fd4114..2a22a9955 100644 --- a/src/strings/nno.json +++ b/src/strings/nno.json @@ -8,8 +8,17 @@ "nn", "nno" ], - "completion": "100% 99.69%", - "missing": [] + "completion": " 88% 96.49%", + "missing": [ + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Search", + "Similar_To", + "Type_A_Word" + ] }, "title": "Apertium | Ei fri/open kjeldekode maskinomsetjingsplattform", "tagline": "Ei fri/open kjeldekode maskinomsetjingsplattform", diff --git a/src/strings/nob.json b/src/strings/nob.json index 7dba11dd2..0f4d24144 100644 --- a/src/strings/nob.json +++ b/src/strings/nob.json @@ -8,8 +8,17 @@ "nb", "nob" ], - "completion": "100% 100.82%", - "missing": [] + "completion": " 88% 97.59%", + "missing": [ + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Search", + "Similar_To", + "Type_A_Word" + ] }, "title": "Apertium | En fri/åpen kildekode maskinoversettelsesplattform", "tagline": "En fri/åpen kildekode maskinoversettelsesplattform", diff --git a/src/strings/oci.json b/src/strings/oci.json index 9b5247c44..956a4ad92 100644 --- a/src/strings/oci.json +++ b/src/strings/oci.json @@ -8,53 +8,47 @@ "oc", "oci" ], - "completion": " 67% 83.23%", + "completion": " 59% 80.56%", "missing": [ "Apertium_Documentation", "Cancel", + "Collapse_Paradigms", + "Dictionary", "Drop_Document", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Install_Apertium", "Install_Apertium_Para", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "description" ] }, "title": "Apertium | Una plataforma liura/open source de traduccion automatica", "tagline": "Una plataforma liura/open source de traduccion automatica", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Traduccion", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Tradusir", "Detect_Language": "Detectar la lenga", "detected": "detectat", "Instant_Translation": "Traduccion instantanèa", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "Traduccion pas encara disponibla !", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", - "Cancel": "%%UNAVAILABLE%% Cancel", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Analisi morfologica", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Analisar", "Morphological_Generation": "Generacion morfologica", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Generar", "Spell_Checker": "Corrector ortografic", "APy_Sandbox": "Nauc de sabla APy", @@ -69,18 +63,14 @@ "Maintainer": "Site mantengut per {{maintainer}}.", "About_Title": "A prepaus del site internet", "Enable_JS_Warning": "Lo site fonciona pas qu'amb Javascript d'activat, se podètz pas activar Javascript, ensajatz las aisinas de traduccions de Prompsit", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", "About": "A prepaus", "Download": "Telecargar", "Contact": "Contacte", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Documentacion", "About_Apertium": "A prepaus d'Apertium", "What_Is_Apertium": "

      Apertium es una plataforma de traduccion automatica liura/open source, concebuda a l'origina per de paras de lengas pròchas, puèi s'es espandit a de paras de lengas mai aluenhadas coma la para anglés-catalan. La plataforma provesís :

      1. un motor de traduccion automatica que depend pas d'una lenga quina que siá
      2. d'aisinas lingüisticas per gerir las donadas necessària a la realizacion d'un sistèma de traduccion automatica per una para de lengas donada
      3. de donadas lingüisticas per un nombre creissent de paras de lengas.

      Apertium presa l'arribada de novèls desvolopaires : se estimatz que podètz melhoratz lo motor, las aisinas o las donadas lingüisticas, esitetz pas a prene contacte amb nosautres.

      ", "Documentation_Para": "La documentacion se tròba sul Wiki dins la seccion Documentacion. Avèm publicat divèrses articles de conferéncias e de revistas, trobaretz una lista sul Wiki dins la seccion Publications.", "Apertium_Downloads": "Telecargaments Apertium", "Downloads_Para": "Las darrièras versions de la bóstia d'aisinas Apertium e tanben las donadas per las paras de lenga son disponiblas sul site de GitHub. Las instruccions per installar Apertium sus las principalas plataformas se tròban sus la pagina d'installacion del Wiki", - "Contact_Para": "

      Lo canal IRC

      Lo biais lo mai rapid per nos contactar. Per aquò far, anatz sus IRC nòstre canal #apertium sul servidor irc.oftc.net, ont trobaretz los utilizaires e desvolopaires d'Apertium.

      La lista de difusion

      Inscrivètz-vos a la lista de difusion d'Apertium, ont podètz postar de messatges mai longs que contenon de suggestions o que tractan de problèmas e tanben discutir d'Apertium d'un biais general.

      Contacte

      Nos podètz contactar via la lista de difusion d'Apertium se trobatz una error, se vesètz un projècte sul qual vos agradariá que trabalhèssem o se nos volètz donar un còp de man.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Contact_Para": "

      Lo canal IRC

      Lo biais lo mai rapid per nos contactar. Per aquò far, anatz sus IRC nòstre canal #apertium sul servidor irc.oftc.net, ont trobaretz los utilizaires e desvolopaires d'Apertium.

      La lista de difusion

      Inscrivètz-vos a la lista de difusion d'Apertium, ont podètz postar de messatges mai longs que contenon de suggestions o que tractan de problèmas e tanben discutir d'Apertium d'un biais general.

      Contacte

      Nos podètz contactar via la lista de difusion d'Apertium se trobatz una error, se vesètz un projècte sul qual vos agradariá que trabalhèssem o se nos volètz donar un còp de man.

      " } diff --git a/src/strings/por.json b/src/strings/por.json index 8ebea2740..b2fadece6 100644 --- a/src/strings/por.json +++ b/src/strings/por.json @@ -9,63 +9,57 @@ "pt", "por" ], - "completion": " 49% 12.32%", + "completion": " 42% 11.92%", "missing": [ "About_Apertium", "Apertium_Documentation", "Apertium_Downloads", "Cancel", + "Collapse_Paradigms", "Contact", "Contact_Para", + "Dictionary", "Documentation", "Documentation_Para", "Download", "Downloads_Para", "Drop_Document", "Enable_JS_Warning", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Install_Apertium", "Install_Apertium_Para", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "What_Is_Apertium", "description" ] }, "title": "Apertium | Uma plataforma livre para a tradução automática", "tagline": "Plataforma livre para a tradução automática", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Tradução", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Traduzir", "Detect_Language": "Detectar língua", "detected": "detectada", "Instant_Translation": "tradução instantânea", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "Tradução aina não disponível!", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", - "Cancel": "%%UNAVAILABLE%% Cancel", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Análise morfológica", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Analisar!", "Morphological_Generation": "Geração morfológica", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Gerar", "Spell_Checker": "Corretor ortográfico", "APy_Sandbox": "Entorno de provas", @@ -79,19 +73,5 @@ "Contact_Us": "Contate-nos se encontrar um erro, pensar um projeto para nós fazermos, ou quiser ajudar.", "Maintainer": "Este website é mantido por {{maintainer}}.", "About_Title": "Sobre este Website", - "Enable_JS_Warning": "%%UNAVAILABLE%% This site only works with JavaScript enabled, if you cannot enable Javascript, then try the translators at Prompsit.", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", - "About": "Sobre", - "Download": "%%UNAVAILABLE%% Download", - "Contact": "%%UNAVAILABLE%% Contact", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", - "Documentation": "%%UNAVAILABLE%% Documentation", - "About_Apertium": "%%UNAVAILABLE%% About Apertium", - "What_Is_Apertium": "%%UNAVAILABLE%%

      Apertium is a free/open-source machine translation platform, initially aimed at related-language pairs but expanded to deal with more divergent language pairs (such as English-Catalan). The platform provides

      1. a language-independent machine translation engine
      2. tools to manage the linguistic data necessary to build a machine translation system for a given language pair and
      3. linguistic data for a growing number of language pairs.

      Apertium welcomes new developers: if you think you can improve the engine or the tools, or develop linguistic data for us, do not hesitate to contact us.

      ", - "Documentation_Para": "%%UNAVAILABLE%% Documentation can be found on our Wiki under the Documentation sub-page. We have published various conference papers and journal articles, a list of which may be found on the Wiki under Publications.", - "Apertium_Downloads": "%%UNAVAILABLE%% Apertium Downloads", - "Downloads_Para": "%%UNAVAILABLE%% Current versions of the Apertium toolbox as well as of language-pair data are available from the GitHub page. Installation instructions for Apertium on all major platforms are provided on the Wiki's Installation page.", - "Contact_Para": "%%UNAVAILABLE%%

      IRC channel

      The quickest way to contact us is by joining our IRC channel, #apertium at irc.oftc.net, where users and developers of Apertium meet. You don't need an IRC client; you can use OFTC webchat.

      Mailing list

      Also, subscribe to the apertium-stuff mailing list, where you can post longer proposals or issues, as well as follow general Apertium discussions.

      Contact

      Feel free to contact us via the apertium-contact mailing list if you find a mistake, there's a project you would like to see us work on, or you would like to help out.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "About": "Sobre" } diff --git a/src/strings/pos/deu.json b/src/strings/pos/deu.json new file mode 100644 index 000000000..db31308d5 --- /dev/null +++ b/src/strings/pos/deu.json @@ -0,0 +1,33 @@ +{ + "n": "Substantiv", + "v": "Verb", + "vblex": "Verb", + "v.tv": "transitives Verb", + "v.iv": "intransitives Verb", + "n.m.nn": "unbelebtes maskulines Substantiv", + "n.m.aa": "belebtes maskulines Substantiv", + "n.f.nn": "unbelebtes feminines Substantiv", + "n.f.aa": "belebtes feminines Substantiv", + "n.nt.nn": "unbelebtes neutrales Substantiv", + "n.nt.aa": "belebtes neutrales Substantiv", + + "nom": "Nominativ", + "acc": "Akkusativ", + "dat": "Dativ", + "loc": "Lokativ", + "gen": "Genitiv", + "abl": "Ablativ", + "ins": "Instrumentalis", + "term": "Terminativ", + "abe": "Abessiv", + + "gna_impf": "Konverb", + + "past": "Vergangenheit", + + "p1": "erste Person", + "p2": "zweite Person", + + "sg": "Singular", + "pl": "Plural" +} diff --git a/src/strings/pos/eng.json b/src/strings/pos/eng.json new file mode 100644 index 000000000..e50e5a670 --- /dev/null +++ b/src/strings/pos/eng.json @@ -0,0 +1,34 @@ +{ + "n": "noun", + "v": "verb", + "vblex": "verb", + "v.tv": "transitive verb", + "v.iv": "intransitive verb", + "n.m.nn": "inanimate masculine noun", + "n.m.aa": "animate masculine noun", + "n.f.nn": "inanimate feminine noun", + "n.f.aa": "animate feminine noun", + "n.nt.nn": "inanimate neutral noun", + "n.nt.aa": "animate neutral noun", + + "nom": "nominative", + "acc": "accusative", + "dat": "dative", + "gen": "genitive", + "loc": "locative", + "abl": "ablative", + "ins": "instrumental", + "term": "terminative", + "abe": "abessive", + + "gna_impf": "imperfect converb", + "imp": "imperative", + + "past": "past", + + "p1": "first person", + "p2": "second person", + + "sg": "singular", + "pl": "plural" +} \ No newline at end of file diff --git a/src/strings/pos/rus.json b/src/strings/pos/rus.json new file mode 100644 index 000000000..e1c1639ca --- /dev/null +++ b/src/strings/pos/rus.json @@ -0,0 +1,25 @@ +{ + "n": "существительное", + "v": "глагол", + "vblex": "глагол", + "v.tv": "переходный глагол", + "v.iv": "непереходный глагол", + "n.m.nn": "неодуш. сущ. муж. рода", + "n.m.aa": "одуш. сущ. муж. рода", + "n.f.nn": "неодуш. сущ. жен. рода", + "n.f.aa": "одуш. сущ. жен. рода", + "n.nt.nn": "неодуш. сущ. ср. рода", + "n.nt.aa": "одуш. сущ. ср. рода", + + "nom": "именительный", + "acc": "винительный", + "dat": "дательный", + "gen": "родительный", + "loc": "местный", + "abl": "исходный", + "ins": "творительный", + "term": "предел", + "abe": "безналичный", + + "gna_impf": "деепричастие" +} \ No newline at end of file diff --git a/src/strings/pos/ukr.json b/src/strings/pos/ukr.json new file mode 100644 index 000000000..50b8ad430 --- /dev/null +++ b/src/strings/pos/ukr.json @@ -0,0 +1,25 @@ +{ + "n": "іменник", + "v": "дієслово", + "vblex": "дієслово", + "v.tv": "перехідне дієслово", + "v.iv": "неперехідне дієслово", + "n.m.nn": "неіст. ім. чол. роду", + "n.m.aa": "іст. ім. чол. роду", + "n.f.nn": "неіст. ім. жін. роду", + "n.f.aa": "іст. ім. жін. роду", + "n.nt.nn": "неіст. ім. сер. роду", + "n.nt.aa": "іст. ім. сер. роду", + + "nom": "називний", + "acc": "знахідний", + "dat": "давальний", + "gen": "родовий", + "loc": "місцевий", + "abl": "відмінок походження", + "ins": "орудний", + "term": "кінцевий", + "abe": "безвідмінковий", + + "gna_impf": "дієприслівник" +} diff --git a/src/strings/ron.json b/src/strings/ron.json index 1dd0c9ccb..34582b313 100644 --- a/src/strings/ron.json +++ b/src/strings/ron.json @@ -8,7 +8,7 @@ "ro", "ron" ], - "completion": " 39% 9.02%", + "completion": " 34% 8.73%", "missing": [ "About", "About_Apertium", @@ -16,15 +16,18 @@ "Apertium_Documentation", "Apertium_Downloads", "Cancel", + "Collapse_Paradigms", "Contact", "Contact_Para", "Contact_Us", + "Dictionary", "Documentation", "Documentation_Para", "Download", "Downloads_Para", "Drop_Document", "Enable_JS_Warning", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Install_Apertium", @@ -32,44 +35,34 @@ "Instant_Translation", "Maintainer", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "What_Is_Apertium", "description" ] }, "title": "Apertium | O platformă liberă de traducere automată", "tagline": "O platformă liberă de traducere automată", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Traducere", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Traducere", "Detect_Language": "Detectarea limbii", "detected": "detectată", - "Instant_Translation": "%%UNAVAILABLE%% Instant translation", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "Traducerea nu este încă disponibilă!", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", - "Cancel": "%%UNAVAILABLE%% Cancel", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Analiză morfologică", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Analizare", "Morphological_Generation": "Generare morfologică", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Generare", "Spell_Checker": "Corector ortografic", "APy_Sandbox": "Cutie cu nisip APy", @@ -79,23 +72,5 @@ "Language": "Limbă", "Input_Text": "Text de intrare", "Notice_Mistake": "Ați observat vreo greșeală?", - "Help_Improve": "Ajutați-ne să îmbunătățim Apertium!", - "Contact_Us": "%%UNAVAILABLE%% Feel free to contact us if you find a mistake, there's a project you would like to see us work on, or you would like to help out.", - "Maintainer": "%%UNAVAILABLE%% This website is maintained by {{maintainer}}.", - "About_Title": "%%UNAVAILABLE%% About this website", - "Enable_JS_Warning": "%%UNAVAILABLE%% This site only works with JavaScript enabled, if you cannot enable Javascript, then try the translators at Prompsit.", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", - "About": "%%UNAVAILABLE%% About", - "Download": "%%UNAVAILABLE%% Download", - "Contact": "%%UNAVAILABLE%% Contact", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", - "Documentation": "%%UNAVAILABLE%% Documentation", - "About_Apertium": "%%UNAVAILABLE%% About Apertium", - "What_Is_Apertium": "%%UNAVAILABLE%%

      Apertium is a free/open-source machine translation platform, initially aimed at related-language pairs but expanded to deal with more divergent language pairs (such as English-Catalan). The platform provides

      1. a language-independent machine translation engine
      2. tools to manage the linguistic data necessary to build a machine translation system for a given language pair and
      3. linguistic data for a growing number of language pairs.

      Apertium welcomes new developers: if you think you can improve the engine or the tools, or develop linguistic data for us, do not hesitate to contact us.

      ", - "Documentation_Para": "%%UNAVAILABLE%% Documentation can be found on our Wiki under the Documentation sub-page. We have published various conference papers and journal articles, a list of which may be found on the Wiki under Publications.", - "Apertium_Downloads": "%%UNAVAILABLE%% Apertium Downloads", - "Downloads_Para": "%%UNAVAILABLE%% Current versions of the Apertium toolbox as well as of language-pair data are available from the GitHub page. Installation instructions for Apertium on all major platforms are provided on the Wiki's Installation page.", - "Contact_Para": "%%UNAVAILABLE%%

      IRC channel

      The quickest way to contact us is by joining our IRC channel, #apertium at irc.oftc.net, where users and developers of Apertium meet. You don't need an IRC client; you can use OFTC webchat.

      Mailing list

      Also, subscribe to the apertium-stuff mailing list, where you can post longer proposals or issues, as well as follow general Apertium discussions.

      Contact

      Feel free to contact us via the apertium-contact mailing list if you find a mistake, there's a project you would like to see us work on, or you would like to help out.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Help_Improve": "Ajutați-ne să îmbunătățim Apertium!" } diff --git a/src/strings/rus.json b/src/strings/rus.json index ca9fb990a..5942a590e 100644 --- a/src/strings/rus.json +++ b/src/strings/rus.json @@ -11,12 +11,13 @@ "ru", "rus" ], - "completion": " 80% 81.71%", + "completion": " 81% 80.75%", "missing": [ "Apertium_Documentation", "Install_Apertium", "Install_Apertium_Para", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", @@ -29,28 +30,20 @@ "title": "Апертиум | Открытая платформа машинного перевода", "tagline": "Открытая платформа машинного перевода", "description": "Apertium — это платформа машинного перевода. Это свободное программное обеспечение, доступное под лицензией GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Перевод", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Перевести", "Detect_Language": "Определить язык", "detected": "определен автоматически", "Instant_Translation": "Мгновенный перевод", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", "Translate_Document": "Перевести документ", "Drop_Document": "Перетащите документ сюда", "Not_Available": "Перевод ещё не доступен!", "File_Too_Large": "Файл слишком большой!", "Cancel": "Отмена", "Format_Not_Supported": "Формат не поддерживается!", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Морфологический анализ", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Анализировать", "Morphological_Generation": "Морфологический синтез", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Синтезировать", "Spell_Checker": "Проверка правописания", "APy_Sandbox": "APy Песочница", @@ -69,7 +62,6 @@ "About": "Об Apertium", "Download": "Загрузки", "Contact": "Связаться с разработчиками", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Документация", "About_Apertium": "Об Apertium", "What_Is_Apertium": "

      Apertium — это открытая платформа машинного перевода. Изначально она была создана для связанных языковых пар, но теперь поддерживает даже такие необычные пары, как английский—каталанский. Платформа предоставляет

      1. независимый от языка машинный переводчик;
      2. инструменты для сбора лингвистических данных для машинного перевода;
      3. лингвистические данные для большого количества языковых пар.

      Apertium приветствует новых разработчиков: если Вы можете улучшить движок машинного перевода или инструменты или собрать лингвистические данные для нас, то свяжитесь с нами.

      ", @@ -77,6 +69,11 @@ "Apertium_Downloads": "Загрузки Apertium", "Downloads_Para": "Текущая версия инструментария Apertium и данные о языковых парах доступны на странице GitHub. Инструкции по установке Apertium на всех основных платформах доступны в вики.", "Contact_Para": "

      Канал IRC

      Самый быстрый способ связаться с нами — это использовать наш IRC канал, #apertium на сервере irc.oftc.net, где общаются пользователи и разработчики. Вам не нужен IRC-клиент, можно использовать вебчат OFTC.

      Список рассылки

      Подпишитесь на наш список рассылки (apertium-stuff). Туда Вы можете писать предложения или ошибки, или просто обсуждать Apertium.

      Ещё один список рассылки

      С нами можно связаться через список рассылки apertium-contact в случае, если Вы нашли ошибку, хотите, чтобы мы поработали над каким-то проектом или хотите помочь.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Dictionary": "Словарь", + "Type_A_Word": "Введите слово", + "Search": "Поиск", + "No_results_found": "Результатов не найдено!", + "Expand_Paradigms": "Словоизменение", + "Collapse_Paradigms": "Скрыть", + "Similar_To": "похоже на" } diff --git a/src/strings/sat.json b/src/strings/sat.json index de41e79ab..c8dd817f2 100644 --- a/src/strings/sat.json +++ b/src/strings/sat.json @@ -7,8 +7,17 @@ "locale": [ "sat" ], - "completion": "100% 108.75%", - "missing": [] + "completion": " 88% 105.26%", + "missing": [ + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Search", + "Similar_To", + "Type_A_Word" + ] }, "title": "Apertium | ᱢᱤᱫᱴᱟᱹᱝ ᱯᱷᱨᱤ/ᱠᱷᱩᱞᱟᱹᱼᱥᱨᱚᱛ ᱢᱮᱥᱤᱱ ᱛᱚᱨᱡᱚᱢᱟ ᱢᱚᱸᱧᱪ", "tagline": "ᱢᱤᱫᱴᱟᱹᱝ ᱯᱷᱨᱤ/ᱠᱷᱩᱞᱟᱹᱼᱥᱨᱚᱛ ᱢᱮᱥᱤᱱ ᱛᱚᱨᱡᱚᱢᱟ ᱢᱚᱸᱧᱪ", diff --git a/src/strings/skr.json b/src/strings/skr.json index 6b026844b..e071c9649 100644 --- a/src/strings/skr.json +++ b/src/strings/skr.json @@ -7,8 +7,17 @@ "locale": [ "skr" ], - "completion": "100% 100.00%", - "missing": [] + "completion": " 88% 97.97%", + "missing": [ + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Search", + "Similar_To", + "Type_A_Word" + ] }, "title": " ‎اپیرٹیئم| ہک مفت/کھلا ماخذ مشینی ترجمہ پلیٹ فارم", "tagline": "ہک مفت/کھلا ماخذ مشینی ترجمہ پلیٹ فارم", diff --git a/src/strings/sme.json b/src/strings/sme.json index 4dcc59e09..6181face9 100644 --- a/src/strings/sme.json +++ b/src/strings/sme.json @@ -9,59 +9,54 @@ "se", "sme" ], - "completion": " 56% 14.70%", + "completion": " 49% 14.23%", "missing": [ "About_Apertium", "Apertium_Documentation", "Apertium_Downloads", + "Collapse_Paradigms", "Contact_Para", + "Dictionary", "Documentation_Para", "Downloads_Para", "Drop_Document", "Enable_JS_Warning", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Install_Apertium", "Install_Apertium_Para", "Instant_Translation", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translation_Help", + "Type_A_Word", "What_Is_Apertium", "description" ] }, "title": "Apertium | Friddja ja rabasgáldokodavuđot dihtorjorgalanvuogádat", "tagline": "Friddja ja rabasgáldokodavuđot dihtorjorgalanvuogádat", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Jorgaleapmi", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Jorgal", "Detect_Language": "Dovdá giela", "detected": "Árvaluvvon giella", - "Instant_Translation": "%%UNAVAILABLE%% Instant translation", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "Jorgalus ii gávdno!", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", "Cancel": "Gaskkalduhte", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", "Translate_Webpage": "Jorgal neahttasiiddu", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Morfologalaš analysa", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Analysere", "Morphological_Generation": "Morfologalaš genereren", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Generere", "Spell_Checker": "Sátnedárkkisteapmi", "APy_Sandbox": "APy-sáttokássa", @@ -75,19 +70,8 @@ "Contact_Us": "Váldde áinnas oktavuođa minguin jus gávnnat meattáhusa, jus dus lea miella bargat prošeavttain dahje don eará ládje háliidat min veahkehit.", "Maintainer": "Dán neahttabáikki fuolaha {{maintainer}}.", "About_Title": "Neahttabáikki birra", - "Enable_JS_Warning": "%%UNAVAILABLE%% This site only works with JavaScript enabled, if you cannot enable Javascript, then try the translators at Prompsit.", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", "About": "Birra", "Download": "Viežžat", "Contact": "Váldde oktavuođa", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", - "Documentation": "Dokumentašuvdna", - "About_Apertium": "%%UNAVAILABLE%% About Apertium", - "What_Is_Apertium": "%%UNAVAILABLE%%

      Apertium is a free/open-source machine translation platform, initially aimed at related-language pairs but expanded to deal with more divergent language pairs (such as English-Catalan). The platform provides

      1. a language-independent machine translation engine
      2. tools to manage the linguistic data necessary to build a machine translation system for a given language pair and
      3. linguistic data for a growing number of language pairs.

      Apertium welcomes new developers: if you think you can improve the engine or the tools, or develop linguistic data for us, do not hesitate to contact us.

      ", - "Documentation_Para": "%%UNAVAILABLE%% Documentation can be found on our Wiki under the Documentation sub-page. We have published various conference papers and journal articles, a list of which may be found on the Wiki under Publications.", - "Apertium_Downloads": "%%UNAVAILABLE%% Apertium Downloads", - "Downloads_Para": "%%UNAVAILABLE%% Current versions of the Apertium toolbox as well as of language-pair data are available from the GitHub page. Installation instructions for Apertium on all major platforms are provided on the Wiki's Installation page.", - "Contact_Para": "%%UNAVAILABLE%%

      IRC channel

      The quickest way to contact us is by joining our IRC channel, #apertium at irc.oftc.net, where users and developers of Apertium meet. You don't need an IRC client; you can use OFTC webchat.

      Mailing list

      Also, subscribe to the apertium-stuff mailing list, where you can post longer proposals or issues, as well as follow general Apertium discussions.

      Contact

      Feel free to contact us via the apertium-contact mailing list if you find a mistake, there's a project you would like to see us work on, or you would like to help out.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Documentation": "Dokumentašuvdna" } diff --git a/src/strings/spa.json b/src/strings/spa.json index 83542cbd2..d8c959ed4 100644 --- a/src/strings/spa.json +++ b/src/strings/spa.json @@ -10,51 +10,50 @@ "es", "spa" ], - "completion": " 71% 26.86%", + "completion": " 62% 26.00%", "missing": [ "Apertium_Documentation", + "Collapse_Paradigms", "Contact_Para", + "Dictionary", "Documentation_Para", "Downloads_Para", "Drop_Document", + "Expand_Paradigms", "Install_Apertium", "Install_Apertium_Para", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", + "Search", + "Similar_To", "Supported_Formats", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "What_Is_Apertium", "description" ] }, "title": "Apertium | Una plataforma libre para la traducción automática", "tagline": "Plataforma libre para la traducción automática", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Traducción", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Traducir", "Detect_Language": "Detectar idioma", "detected": "detectado", "Instant_Translation": "Traducción instantánea", "Mark_Unknown_Words": "Marcar palabras desconocidas", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", "Translate_Document": "Traducir un documento", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "Traducción todavía no disponible!", "File_Too_Large": "¡El fichero es demasiado grande!", "Cancel": "Cancelar", "Format_Not_Supported": "Formato desconocido!", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Análisis morfológico", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Analizar", "Morphological_Generation": "Generación morfológica", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Generar", "Spell_Checker": "Corrector ortográfico", "APy_Sandbox": "Entorno de pruebas", @@ -73,14 +72,7 @@ "About": "Acerca de", "Download": "Descargas", "Contact": "Contactar", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Documentación", "About_Apertium": "Acerca de Apertium", - "What_Is_Apertium": "%%UNAVAILABLE%%

      Apertium is a free/open-source machine translation platform, initially aimed at related-language pairs but expanded to deal with more divergent language pairs (such as English-Catalan). The platform provides

      1. a language-independent machine translation engine
      2. tools to manage the linguistic data necessary to build a machine translation system for a given language pair and
      3. linguistic data for a growing number of language pairs.

      Apertium welcomes new developers: if you think you can improve the engine or the tools, or develop linguistic data for us, do not hesitate to contact us.

      ", - "Documentation_Para": "%%UNAVAILABLE%% Documentation can be found on our Wiki under the Documentation sub-page. We have published various conference papers and journal articles, a list of which may be found on the Wiki under Publications.", - "Apertium_Downloads": "Descargas de Apertium", - "Downloads_Para": "%%UNAVAILABLE%% Current versions of the Apertium toolbox as well as of language-pair data are available from the GitHub page. Installation instructions for Apertium on all major platforms are provided on the Wiki's Installation page.", - "Contact_Para": "%%UNAVAILABLE%%

      IRC channel

      The quickest way to contact us is by joining our IRC channel, #apertium at irc.oftc.net, where users and developers of Apertium meet. You don't need an IRC client; you can use OFTC webchat.

      Mailing list

      Also, subscribe to the apertium-stuff mailing list, where you can post longer proposals or issues, as well as follow general Apertium discussions.

      Contact

      Feel free to contact us via the apertium-contact mailing list if you find a mistake, there's a project you would like to see us work on, or you would like to help out.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Apertium_Downloads": "Descargas de Apertium" } diff --git a/src/strings/srd.json b/src/strings/srd.json index 1855c178b..f385f0bf2 100644 --- a/src/strings/srd.json +++ b/src/strings/srd.json @@ -5,45 +5,46 @@ "locale": [ "srd" ], - "completion": " 82% 90.82%", + "completion": " 71% 87.91%", "missing": [ "Apertium_Documentation", + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", "Install_Apertium", "Install_Apertium_Para", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", + "Search", + "Similar_To", "Supported_Formats", "Translate_Webpage", - "Translation_Help" + "Translation_Help", + "Type_A_Word" ] }, "title": "Apertium | Una prataforma lìbera a còdighe abertu pro sa tradutzione automàtica", "tagline": "Una prataforma lìbera a còdighe abertu pro sa tradutzione automàtica", "description": "Apertium est una prataforma de tradutzione automàtica basada subra de règulas. Est unu programa lìberu publicadu suta sas cunditziones de sa GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Tradutzione", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Borta", "Detect_Language": "Rileva sa limba in manera automàtica", "detected": "rilevada", "Instant_Translation": "Tradutzione istantànea", "Mark_Unknown_Words": "Sinnala sas paràulas disconnotas", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", "Translate_Document": "Borta unu documentu", "Drop_Document": "Traga unu documentu", "Not_Available": "Sa tradutzione no est galu a disponimentu!", "File_Too_Large": "S'archìviu est tropu mannu!", "Cancel": "Cantzella", "Format_Not_Supported": "Su formadu no est suportadu!", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Anàlisi morfològica", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Analiza", "Morphological_Generation": "Generatzione morfològica", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Gènera", "Spell_Checker": "Curretore ortogràficu", "APy_Sandbox": "APy sandbox", @@ -62,14 +63,11 @@ "About": "Informatziones", "Download": "Iscàrriga", "Contact": "Cuntatade·nos", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Documentatzione", "About_Apertium": "Subra de Apertium", "What_Is_Apertium": "

      Apertium est una prataforma de tradutzione automàtica lìbera e a còdighe abertu, a su cumintzu creada pro una paja de limbas serentes, e posca ampliada Sa prataforma frunit

      1. unu motore de tradutzione automàtica indipendente dae sa limba
      2. ainas pro gestire sos datos linguìsticos e netzessàrios pro fraigare unu sistema de tradutzione pro una cumbinatzione linguìstica dislindada e
      3. datos linguìsticos pro unu nùmeru in crèschida de còpias de limbas.

      Apertium dat su bene bènnidu a isvilupadores noos: si pensades chi si potzat megiorare su motore, sas ainas o chi si potzant isvilupare sos datos linguìsticos cuntatade·nos.

      ", "Documentation_Para": "Podides agatare sa documentatzione in sa wiki nostra, in sa pàgina Documentation. Amus publicadu paritzos artìculos e cunferèntzias. Agatades sa lista intrea in sa wiki, in sa pàgina Publications.", "Apertium_Downloads": "Iscarrigamentos de Apertium", "Downloads_Para": "Sas versiones atuales de Apertium e sos datos linguìsticos sunt a disponimentu in sa pàgina de GitHub. Sas istrutziones de installatzione de Apertium in sa majoria de sas prataformas sunt a disponimentu in sa pagina Installation de sa wiki.", - "Contact_Para": "

      Canale IRC

      Sa manera prus lestra de nos cuntatare est intrende a su canale IRC nostru, #apertium in irc.oftc.net, in ue bi sunt sos utentes e sos isvilupadores de Apertium. Si non tenides perunu cliente IRC; podides impreare su webchat de OFTC.

      Lista de messàgios

      Podides fintzas aderire a sa lista de messàgios apertium-stuff, in ue podides iscriere propostas, chistionare de problemas e sighire chistiones generales de Apertium.

      Cuntatu

      Cuntatade·nos tràmite sa lista de messàgios apertium-contact si agatades carchi faddina, si cherides chi traballemus a carchi progetu o si cherides collaborare.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Contact_Para": "

      Canale IRC

      Sa manera prus lestra de nos cuntatare est intrende a su canale IRC nostru, #apertium in irc.oftc.net, in ue bi sunt sos utentes e sos isvilupadores de Apertium. Si non tenides perunu cliente IRC; podides impreare su webchat de OFTC.

      Lista de messàgios

      Podides fintzas aderire a sa lista de messàgios apertium-stuff, in ue podides iscriere propostas, chistionare de problemas e sighire chistiones generales de Apertium.

      Cuntatu

      Cuntatade·nos tràmite sa lista de messàgios apertium-contact si agatades carchi faddina, si cherides chi traballemus a carchi progetu o si cherides collaborare.

      " } diff --git a/src/strings/swe.json b/src/strings/swe.json index 13152a08b..d93a8cda9 100644 --- a/src/strings/swe.json +++ b/src/strings/swe.json @@ -7,46 +7,46 @@ "locale": [ "swe" ], - "completion": " 80% 85.70%", + "completion": " 70% 82.95%", "missing": [ "Apertium_Documentation", + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", "Install_Apertium", "Install_Apertium_Para", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", + "Search", + "Similar_To", "Supported_Formats", "Translate_Webpage", - "Translation_Help" + "Translation_Help", + "Type_A_Word" ] }, "title": "Apertium | En fri maskinöversättningsplattform i öppen källkod", "tagline": "En fri maskinöversättningsplattform i öppen källkod", "description": "Apertium är en regelbaserad maskinöversättningsplatform. It is free software and released under the terms of the GNU General Public License. Det är fri mjukvara som är utgiven under villkoren i GNU General Public License", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Översättning", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Översätt", "Detect_Language": "Detektera språk", "detected": "detekterat", "Instant_Translation": "Omedelbar översättning", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", "Translate_Document": "Översätt ett dokument", "Drop_Document": "Släpp ett dokument", "Not_Available": "Översättning ej ännu tillgänglig!", "File_Too_Large": "Filen är för stor!", "Cancel": "Avbryt", "Format_Not_Supported": "Formatet stöds inte!", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Morfologisk analys", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Analys", "Morphological_Generation": "Morfologisk generering", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Generera", "Spell_Checker": "Stavningskontroll", "APy_Sandbox": "APy sandlåda", @@ -65,14 +65,11 @@ "About": "Om", "Download": "Nedladdning", "Contact": "Kontakt", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Dokumentation", "About_Apertium": "Om Apertium", "What_Is_Apertium": "

      Apertium är en En fri maskinöversättningsplattform i öppen källkod, ursprungligen ägnad till besläktade språkpar, men utvidgad till att hantera mer olikartade språkpar (som Engelska-Katalanska). Plattformen tillhandahåller

      1. en språkoberoende maskinöversättningsmotor
      2. verktyg för att hantera de linguistiska data som behövs för ett visst språkpar och
      3. Linguistiska data för ett växande antal språkpar.

      Apertium välkomnar nya utvecklare: om du tror att du kan förbättra motorn eller verktygen, eller utveckla linguistiska data åt oss, tveka inte attkontakta oss.

      ", "Documentation_Para": "Dokumentation hittar du på vår Wiki under Documentation undersida. Vi har publicerat diverse konferensbidrag och tidningsartiklar, du hittar en lista på dem på Wikin under Publications.", "Apertium_Downloads": "Apertium Nedladdningar", "Downloads_Para": "Aktuell version av Apertium toolbox liksom av språkparsdata är tillgängliga på GitHub-sidan. Installationsinstruktioner för Apertium på alla större plattformar tillhandahålls på Wikins Installation-sida.", - "Contact_Para": "

      IRC-kanalen

      Det snabbaste sättet att kontakta oss är att ansluta sig till IRC -kanal, #apertium på irc.oftc.net, där användare och utvecklare av Apertium träffas. Du behöver inte någon IRC-klient; du kan använda OFTC webchat.

      E-postlista

      Prenumerera också på e-postlistan apertium-stuff, där du kan publicera längre förslag eller problem, liksom följa allmänna Apertium-diskussioner.

      Kontakt

      Kontakta oss gärna på e-postlistan apertium-contact om du hittar ett misstag, du vill att vi tar oss an ett projekt, eller om du skulle vilja hjälpa till.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Contact_Para": "

      IRC-kanalen

      Det snabbaste sättet att kontakta oss är att ansluta sig till IRC -kanal, #apertium på irc.oftc.net, där användare och utvecklare av Apertium träffas. Du behöver inte någon IRC-klient; du kan använda OFTC webchat.

      E-postlista

      Prenumerera också på e-postlistan apertium-stuff, där du kan publicera längre förslag eller problem, liksom följa allmänna Apertium-diskussioner.

      Kontakt

      Kontakta oss gärna på e-postlistan apertium-contact om du hittar ett misstag, du vill att vi tar oss an ett projekt, eller om du skulle vilja hjälpa till.

      " } diff --git a/src/strings/szl.json b/src/strings/szl.json index f26ebaad5..192244117 100644 --- a/src/strings/szl.json +++ b/src/strings/szl.json @@ -7,16 +7,23 @@ "locale": [ "szl" ], - "completion": " 97% 101.22%", + "completion": " 84% 97.97%", "missing": [ "Apertium_Documentation", - "Norm_Preferences" + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word" ] }, "title": "Apertium | Darmowŏ platforma przekładu maszinowego ze ôtwartym zdrzōdłym", "tagline": "Darmowŏ platforma przekładu maszinowego ze ôtwartym zdrzōdłym", "description": "Apertium to je platforma maszinowego przekładu, co bazuje na prawidłach. To je darmowy software ôpublikowany podle warōnkōw Gyneralnyj Licyncyje Publicznyj GNU.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Przekłŏd", "Translation_Help": "Wkludź tekst abo adresã URL do przekładu.", "Translate": "Przełōż", @@ -56,7 +63,6 @@ "About": "Informacyje", "Download": "Ściōng", "Contact": "Kōntakt", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Dokumyntacyjŏ", "About_Apertium": "Ô Apertium", "What_Is_Apertium": "

      Apertium to je darmowŏ platforma przekładu maszinowego ze ôtwartym zdrzōdłym, nojprzōd przigotowanŏ dlŏ bliskich sobie pŏr, ale rozszyrzōnŏ, żeby wiedzieć sie rady ze barzij rozmajtymi pŏrami (bez przikłŏd angelsko-katalōńskŏ). Platforma dŏwŏ

      1. niyzależny ôd gŏdki motōr przekładu maszinowego
      2. nŏczynie do regyrowaniŏ danymi lingwistycznymi potrzebnymi do budowy systymu maszinowego przekładu dlŏ danyj pŏry i
      3. dane lingwistyczne corŏz srogszyj liczby pŏr gŏdek.

      Apertium rŏd widzi nowych deweloperōw: jak myślisz, iże możesz ulepszyć motōr abo nŏczynie, abo zbudować dane lingwistyczne dlō nŏs, zarŏz sie z nami skōntaktuj.

      ", diff --git a/src/strings/tat.json b/src/strings/tat.json index 7015f3081..c4a167534 100644 --- a/src/strings/tat.json +++ b/src/strings/tat.json @@ -9,16 +9,23 @@ "tt", "tat" ], - "completion": " 97% 104.45%", + "completion": " 84% 101.10%", "missing": [ "Apertium_Documentation", - "Norm_Preferences" + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word" ] }, "title": "Apertium | Ирекле/ачык чыганак кодлы бер автоматик тәрҗемә платформасы", "tagline": "Ирекле/ачык чыганак кодлы бер автоматик тәрҗемә платформасы", "description": "Apertium — кагыйдәләргә нигезләнгән автоматик тәрҗемә платформасы. Ул ирекле программа тәэминаты булып тора һәм GNU General Public лицензиясе шартлары белән нәшер ителә.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Тәрҗемә", "Translation_Help": "Тәрҗемә ителәсе текстны я сылтаманы кертегез.", "Translate": "Tәржемә итү", @@ -58,7 +65,6 @@ "About": "Сайт турында", "Download": "Йөкләү", "Contact": "Элемтә", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Документация", "About_Apertium": "Apertium турында", "What_Is_Apertium": "

      Apertium — ирекле/ачык чыганак кодлы бер автоматик тәрҗемә платформасы. Башта ул тугандаш телләргә тәгаенләнгән булса да, соңрак инглизчә-каталанча кебек бер-берсеннән ныграк аеырылып торучы телләр өчен дә гомумиләштерелә. Платформа түбәндәгеләрне тәэмин итә:

      1. телгә бәйсез бер автоматик тәрҗемә моторы
      2. араларында тәрҗемә ителәчәк ике тел өчен кирәкле тел бирелгәннәрен юнәтү өчен кораллар һәм
      3. саны артканнан-арта барган тел парлары өчен тел бирелгәннәре.

      Apertium яңа катнашучыларга ачык: моторны я коралларны яхшырта аласыз дип яки безнең өчен тел бирелгәннәре җитештерә аласыз дип уйлыйсыз икән, безнең белән элемтәгә керегез.

      ", diff --git a/src/strings/tha.json b/src/strings/tha.json index a277642ae..4971cb776 100644 --- a/src/strings/tha.json +++ b/src/strings/tha.json @@ -5,48 +5,46 @@ "locale": [ "tha" ], - "completion": " 76% 75.08%", + "completion": " 67% 72.67%", "missing": [ "Apertium_Documentation", + "Collapse_Paradigms", + "Dictionary", "Drop_Document", + "Expand_Paradigms", "Install_Apertium", "Install_Apertium_Para", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", + "Search", + "Similar_To", "Supported_Formats", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "description" ] }, "title": "อาเปอร์เทียม | แพรตฟอร์มเครื่องแปลภาษาเสรี/โอเพนซอร์ส", "tagline": "แพรตฟอร์มเครื่องแปลภาษาเสรี/โอเพนซอร์ส", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "การแปล", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "แปล", "Detect_Language": "ตรวจหาภาษา", "detected": "ได้ตรวจหาแล้ว", "Instant_Translation": "การแปลแบบทันที", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", "Translate_Document": "แปลเอกสาร", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "การแปลยังไม่พร้อม", "File_Too_Large": "ไฟล์ใหญ่เกินไป", "Cancel": "ยกเลิก", "Format_Not_Supported": "รูปแบบยังไม่ถูกรองรับ", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "การวิเคราะห์วจีวิภาค", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "วิเคราะห์", "Morphological_Generation": "การสร้างทางวิจีวิภาค", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "สร้าง", "Spell_Checker": "ตรวจสอบการสะกด", "APy_Sandbox": "กล่องทรายเอพีวาย", @@ -65,14 +63,11 @@ "About": "เกี่ยวกัย", "Download": "ดาวโหลด", "Contact": "ติดต่อ", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "เอกสาร", "About_Apertium": "เกี่ยวกับอาเปอร์เทียม", "What_Is_Apertium": "

      อาเปอร์เทียมคือแพลตฟอร์มเครื่องแปลเสรี/โอเพนซอร์ส แต่เดิมทีมุ่งไปที่คู่ภาษาที่มีความเกี่ยวข้องกันแต่ขยายให้จัดกับกับคู่ภาษาที่ต่างกันมากขึ้นได้ (เช่น ภาษาอังกฤษ-ภาษาคาตาลัน) แพลตฟอร์มให้บริการ

      1. เอนจินเครื่องแปลภาษาที่ไม่ขึ้นกับภาษา
      2. เครื่องมือที่ใช้จัดการข้อมูลทางภาษาศาสตร์ที่จำเป็นสำหรับการสร้างระบบเครื่องแปลภาษาสำหรับภาษาที่จะแปลและ
      3. ข้อมูลทางภาษาศาสตร์สำหรับเพิ่มจำนวนคู่ภาษา

      อาเปอร์เทียมยินดีต้อนรับนักพัฒนาใหม่ทั้งหลาย: ถ้าคุณคิดว่าคุณสามารถปรับปรุงเอนจินและเครื่องมือทั้งหลาย หรือพัฒนาข้อมูลทางภาษาศาสตร์สำหรับเรา อย่าลังเลที่จะติดต่อเรา.

      ", "Documentation_Para": "เอกสารสามารถหาพบได้ที่วิกิในหน้าย่อยเอกสาร เราได้ตีพิมพ์เอกสารในการประชุมวิชาการและบทความในวารสารมากมาย รายการอาจจะพบได้ในวิกิการตีพิมพ์.", "Apertium_Downloads": "ดาวโหลดอาเปอร์เทียม", "Downloads_Para": "รุ่นปัจจุบันของกล่องเครื่องมืออาเปอร์เทีย, where you can post longer proposals or issues,มอีกทั้งข้อมูลคู่ภาษาอยู่ที่หน้าของ GitHub วิธีการติดตั้งสำหรับอาเปอร์เทียมบนแพลตฟอร์มหลักทั้งหมดมีให้ที่หน้าการติดตั้งที่วิกิ.", - "Contact_Para": "

      ช่องไออาร์ซี

      วิธีที่เร็วที่สุดที่จะติดต่อเราโดยเข้าร่วมไออาร์ซีที่ช่อง #apertium ที่ irc.oftc.net ที่ผู้ใช้และนักพัฒนาทั้งหลายของอาเปอร์เทียมพบกัน คุณไม่จำเป็นต้องใช้ไออาร์ซีไคลเอนต์ คุณสามารถใช้โปรแกรมแชทบนเว็บของฟรีโหนด.

      Mailing list

      อีกทั้งยังสามารถบอกรับเมล์ที่ apertium-stuff mailing list ที่คุณสามารถโพสข้อเสนอหรือประเด็นที่ยาวขึ้น พร้อมทั้งติดตามการอภิปรายโดยทั่วไปของอาเปอร์เทียม

      ติดต่อ

      อย่าลังเลที่จะติดต่อเราโดย apertium-contact mailing list ถ้าคุณพบข้อผิดพลาดหรือมีโครงการที่คุณต้องการเห็นเราทำหรือที่คุณต้องการช่วย

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Contact_Para": "

      ช่องไออาร์ซี

      วิธีที่เร็วที่สุดที่จะติดต่อเราโดยเข้าร่วมไออาร์ซีที่ช่อง #apertium ที่ irc.oftc.net ที่ผู้ใช้และนักพัฒนาทั้งหลายของอาเปอร์เทียมพบกัน คุณไม่จำเป็นต้องใช้ไออาร์ซีไคลเอนต์ คุณสามารถใช้โปรแกรมแชทบนเว็บของฟรีโหนด.

      Mailing list

      อีกทั้งยังสามารถบอกรับเมล์ที่ apertium-stuff mailing list ที่คุณสามารถโพสข้อเสนอหรือประเด็นที่ยาวขึ้น พร้อมทั้งติดตามการอภิปรายโดยทั่วไปของอาเปอร์เทียม

      ติดต่อ

      อย่าลังเลที่จะติดต่อเราโดย apertium-contact mailing list ถ้าคุณพบข้อผิดพลาดหรือมีโครงการที่คุณต้องการเห็นเราทำหรือที่คุณต้องการช่วย

      " } diff --git a/src/strings/tur.json b/src/strings/tur.json index b2e9dd907..1fc9276e6 100644 --- a/src/strings/tur.json +++ b/src/strings/tur.json @@ -9,16 +9,23 @@ "tr", "tur" ], - "completion": " 97% 103.25%", + "completion": " 84% 99.94%", "missing": [ "Apertium_Documentation", - "Norm_Preferences" + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", + "More_Languages", + "No_results_found", + "Norm_Preferences", + "Search", + "Similar_To", + "Type_A_Word" ] }, "title": "Apertium | Özgür ve açık kaynak kodlu bir makine çevirisi platformu", "tagline": "Özgür ve açık kaynak kodlu bir makine çevirisi platformu", "description": "Apertium kural tabanlı bir makine çevirisi platformudur. Apertium özgür yazılımdır, ve dağıtımı GNU Genel Kamu Lisansı ile yapılır.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Çeviri", "Translation_Help": "Cevrilecek bir metin veya web bağlantısı giriniz.", "Translate": "Çevir", @@ -58,7 +65,6 @@ "About": "Hakkımızda", "Download": "İndir", "Contact": "İletişim", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Belgeler", "About_Apertium": "Apertium hakkında", "What_Is_Apertium": "

      Apertium Özgür ve açık kaynak kodlu bir makine çevirisi platformudur. Başlangıçta yakından ilişkili dillerin çevirisi hedeflenmiş olsa da, kapsamı daha farklı dilleri de kapsayacak şekilde genişletilmiştir (örneğin İngilizce-Katalanca). Platform aşağıdakileri sağlar

      1. dilden bağamsız bir makine çevirisi motoru
      2. çevirisi yapılacak dil ikilileri için gerekli dil verilerini yönetecek araçlar
      3. artan sayıda dil ikilisi için dil verisi

      Apertium yeni geliştiricilere açıktır: motoru ve araçları geliştirebileceğinizi ya da bizim için dil verisi derleyebileceğinizi düşünüyorsanız, bizimle iletişim kurun kurun.

      ", diff --git a/src/strings/uig.json b/src/strings/uig.json index 97324ef58..964375537 100644 --- a/src/strings/uig.json +++ b/src/strings/uig.json @@ -8,53 +8,47 @@ "ug", "uig" ], - "completion": " 67% 77.88%", + "completion": " 59% 75.38%", "missing": [ "Apertium_Documentation", "Cancel", + "Collapse_Paradigms", + "Dictionary", "Drop_Document", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Install_Apertium", "Install_Apertium_Para", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "description" ] }, "title": "Apertium | ھەقسىز ۋە ئوچۇق كودلۇق ماشىنا تەرجىمە سۇپىسى", "tagline": "ھەقسىز ۋە ئوچۇق كودلۇق ماشىنا تەرجىمە سۇپىسى", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "تەرجىمان", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "تەرجىمە قىلىش", "Detect_Language": "ئاپتوماتىك بايقاش", "detected": "ئاپتوماتىك بايقالغان", "Instant_Translation": "ھازىر جاۋاب تەرجىمە", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "ھازىرچە تەرجىمە قىلىنمىدى.", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", - "Cancel": "%%UNAVAILABLE%% Cancel", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "مورفولوگىيەلىك ئانالىز", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "ئانالىز قىلىش", "Morphological_Generation": "مورفولوگىيەلىك ھاسىللاش", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "ھاسىللاش", "Spell_Checker": "ئىملاچى", "APy_Sandbox": "APy sandbox", @@ -69,18 +63,14 @@ "Maintainer": "مەزكۇر بېكەت {{maintainer}} تەرىپىدىن ئاسرىلىدۇ.", "About_Title": "مەزكۇر بېكەت ھەققىدە", "Enable_JS_Warning": "مەزكۇر بېكەتنىڭ تورمال ئىشلىتىش ئۈچۈن تور كۆرگۈچنىڭ JavaScript ئىقتىدارى ئوچۇق بولۇشى كېرەك. ئەگەر Javascript نى ئېچىشتا قېيىنچىلىققا ئۇچرىسىڭىز Prompsit دىكى تەرجىمانلارنى سىناپ كۆرۈڭ.", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", "About": "ھەققىدە", "Download": "چۈشۈرۈش", "Contact": "ئالاقىلىشىش", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "قوللانما", "About_Apertium": "Apertium ھەققىدە", "What_Is_Apertium": "

      Apertium بولسا ھەقسىز ۋە ئوچۇق كودلۇق ماشىنا تەرجىمە سۇپىسى بولۇپ، ئەڭ دەسلەپتە يېقىن تىللار ئارىسىدىكى تەرجىمە ئۈچۈن تۈزۈلگەن ۋە كېينچە تېخىمۇ كېڭەيتىلىپ خىلمۇخىل تىللارنى قوللايدىغان بولغان (مەسىلەن ئىنگلىزچە-كاتالانچە).

      1. تىلغا بېقنمايدىغان ماشىنا تەرجىمە ماتورى
      2. ماشىنا تەرجىمە سىستېمىسىنى قۇرۇشقا كېرەكلىك بولىدىغان تىل ئۇچۇرلىرىنى باشقۇرۇش قۇراللىرى
      3. ئۈزلۈكسىز توپلىنىۋاتقان تىل ئۇچۇرلىرى

      Apertium ئىجادىيەت سېپىگە قوشۇلۇشىڭىزنى قارشى ئالىمىز. ئەگەر تەرجىمە ماتورى ياكى قۇراللارنىڭ مۇكەممەلىشىشىگە ياردەم قىلالىسىڭىز ۋە ياكى تىل ئۇچۇر ئامبارلىرىنى قۇرالىسىڭىز بىز بىلەن ئالاقە قىلغايسىز .

      ", "Documentation_Para": "قوللانمىنى تور بەت ۋىكىسىنىڭ Documentation ناملىق تارماق بېتىدىن تاپالايسىز. بىز يەنە بىر قىسىم يىغىن ۋە ژورناللاردا ماقالە ئېلان قىلدۇق. ئۇلارنىڭ تىزىملىكىنى Publications بېتىدىن تاپالايسىز.", "Apertium_Downloads": "Apertium نى چۈشۈرۈش", "Downloads_Para": "Apertium toolbox ۋە language-pair data نىڭ نۆۋەتتىكى نەشرىنى GitHub دىن چۈشۈرەلەيسىز. Apertium نى ھەرخىل مەشغۇلات سۇپىلىرىغا قاچىلاش قوللانمىسىنى ۋىكىنىڭ قاچىلاش بېتى تەمىنلەندى.", - "Contact_Para": "

      IRC قانىلى

      بىز بىلەن ئالاقە قىلىشنىڭ ئەڭ تېز ئۇسۇلى بولسا IRC قانىلىمىزغا (apertium# at irc.oftc.net) قاتنىشىش. بۇ ئاچقۇچىلار بىلەن ئىشلەتكۈچىلەر ئۇچرىشىدىغان كۆڭۈلدىكىدەك ئورۇن بولۇپ، قاتنىشىش ئۈچۈن IRC پروگراممىسى زۆرۈر بولمايدۇ؛ پەقەت OFTC webchat نى ئىشلەتسىڭىزلا كۇپايە.

      ئېلخەت توپى

      يەنە، apertium-stuff mailing list ئېلخەت توپىغا تىزىملىتىڭ. شۇندىلا بىر قەدەر ئۇزۇن يازمىلارنى يازالايسىز ۋە توپتىكى ئەزالارنىڭ مۇنازېرىسىگە قاتنىشالايسىز.

      ئالاقىلىشىڭ

      ئەگەر بىرەر خاتالىق بايقىسىڭىز apertium-stuff mailing list ئارقىلىق بىز بىلەن خالىغان ۋاقىتتا ئالاقىلىشىڭ.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Contact_Para": "

      IRC قانىلى

      بىز بىلەن ئالاقە قىلىشنىڭ ئەڭ تېز ئۇسۇلى بولسا IRC قانىلىمىزغا (apertium# at irc.oftc.net) قاتنىشىش. بۇ ئاچقۇچىلار بىلەن ئىشلەتكۈچىلەر ئۇچرىشىدىغان كۆڭۈلدىكىدەك ئورۇن بولۇپ، قاتنىشىش ئۈچۈن IRC پروگراممىسى زۆرۈر بولمايدۇ؛ پەقەت OFTC webchat نى ئىشلەتسىڭىزلا كۇپايە.

      ئېلخەت توپى

      يەنە، apertium-stuff mailing list ئېلخەت توپىغا تىزىملىتىڭ. شۇندىلا بىر قەدەر ئۇزۇن يازمىلارنى يازالايسىز ۋە توپتىكى ئەزالارنىڭ مۇنازېرىسىگە قاتنىشالايسىز.

      ئالاقىلىشىڭ

      ئەگەر بىرەر خاتالىق بايقىسىڭىز apertium-stuff mailing list ئارقىلىق بىز بىلەن خالىغان ۋاقىتتا ئالاقىلىشىڭ.

      " } diff --git a/src/strings/ukr.json b/src/strings/ukr.json new file mode 100644 index 000000000..2f6983a28 --- /dev/null +++ b/src/strings/ukr.json @@ -0,0 +1,75 @@ +{ + "@metadata": { + "authors": [ + "Alina Vykliuk" + ], + "last-updated": "2017-01-09", + "locale": [ + "uk", + "ukr" + ], + "completion": "100% 100.91%", + "missing": [] + }, + "title": "Апертіум | Безкоштовна/відкрита платформа машинного перекладу", + "tagline": "Безкоштовна/відкрита платформа машинного перекладу", + "description": "Апертіум — це платформа машинного перекладу на основі правил. Це програмне забезпечення є вільним та поширюється відповідно до умов ліцензії GNU General Public License.", + "Apertium_Documentation": "Документація Апертіум", + "Translation": "Переклад", + "Translation_Help": "Введіть текст або URL для перекладу.", + "Translate": "Перекласти", + "Detect_Language": "Визначити мову", + "detected": "визначено", + "Instant_Translation": "Миттєвий переклад", + "Mark_Unknown_Words": "Позначати невідомі слова", + "Multi_Step_Translation": "Багатокроковий переклад (експериментально)", + "Translate_Document": "Перекласти документ", + "Drop_Document": "Перетягніть документ", + "Not_Available": "Переклад наразі недоступний!", + "File_Too_Large": "Файл занадто великий!", + "Cancel": "Скасувати", + "Format_Not_Supported": "Формат не підтримується", + "Translate_Webpage": "Перекласти вебсторінку", + "Supported_Formats": "Підтримувані формати: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 і новіші).
      Файли Word 97 .doc та pdf не підтримуються.", + "Morphological_Analysis": "Морфологічний аналіз", + "Morphological_Analysis_Help": "Введіть текст для морфологічного аналізу.", + "Analyze": "Аналізувати", + "Morphological_Generation": "Морфологічна генерація", + "Morphological_Generation_Help": "Введіть морфологічні форми, які ви хочете згенерувати у текст.", + "Generate": "Згенерувати", + "Spell_Checker": "Перевірка орфографії", + "APy_Sandbox": "Пісочниця APy", + "APy_Sandbox_Help": "Надіслати довільні запити", + "APy_Request": "Запит APy", + "Request": "Запит", + "Language": "Мова", + "Input_Text": "Вхідний текст", + "Notice_Mistake": "Помітили помилку?", + "Help_Improve": "Допоможіть нам покращити Apertium!", + "Contact_Us": "Звертайтеся до нас, якщо знайдете помилку, маєте ідею для проєкту або хочете допомогти.", + "Maintainer": "Цей вебсайт підтримує {{maintainer}}.", + "More_Languages": "Шукаєте більше мов? Спробуйте {{more_languages}}.", + "About_Title": "Про цей вебсайт", + "Enable_JS_Warning": "Цей сайт працює лише з увімкненим JavaScript. Якщо ви не можете увімкнути JavaScript, спробуйте перекладачі від Prompsit.", + "Not_Found_Error": "Помилка 404: Вибачте, такої сторінки більше не існує!", + "About": "Про сайт", + "Download": "Завантаження", + "Contact": "Контакти", + "Norm_Preferences": "Налаштування стилю", + "Documentation": "Документація", + "About_Apertium": "Про Apertium", + "What_Is_Apertium": "

      Apertium — це безкоштовна/відкрита платформа машинного перекладу, яка спочатку була розроблена для споріднених мовних пар, але згодом розширена для більш віддалених мовних пар (наприклад, англійська-каталонська). Платформа пропонує:

      1. незалежний від мови рушій машинного перекладу;
      2. інструменти для керування лінгвістичними даними, необхідними для створення системи перекладу для певної мовної пари;
      3. лінгвістичні дані для дедалі більшої кількості мовних пар.

      Apertium завжди рада новим розробникам: якщо ви хочете вдосконалити рушій або інструменти, або створити лінгвістичні дані для нас — не вагайтеся зв'язатися з нами.

      ", + "Documentation_Para": "Документацію можна знайти на нашій Вікі на сторінці Документація. Ми опублікували кілька конференційних доповідей та наукових статей, список яких доступний на Вікі на сторінці Публікації.", + "Apertium_Downloads": "Завантаження Apertium", + "Downloads_Para": "Актуальні версії інструментів Apertium, а також дані мовних пар доступні на нашій сторінці GitHub. Інструкції з встановлення Apertium для всіх основних платформ наведені на сторінці Встановлення у Вікі.", + "Contact_Para": "

      IRC-канал

      Найшвидший спосіб зв'язатися з нами — приєднатися до нашого IRC-каналу #apertium на irc.oftc.net, де зустрічаються користувачі та розробники Apertium. Вам не потрібен IRC-клієнт — можна скористатися OFTC webchat.

      Список розсилки

      Також можна підписатися на список розсилки apertium-stuff, де можна надсилати пропозиції чи питання, а також слідкувати за загальними обговореннями Apertium.

      Контакти

      Якщо ви помітили помилку, маєте ідею для проекту або хочете допомогти, не соромтеся зв'язатися з нами через список розсилки apertium-contact.

      ", + "Install_Apertium": "Встановлення Apertium", + "Install_Apertium_Para": "Відчуваєте повільну роботу? Наші сервери можуть бути перевантажені. Дізнайтеся, як встановити Apertium локально.", + "Dictionary": "Словник", + "Type_A_Word": "Введіть слово", + "Search": "Пошук", + "No_results_found": "Результатів не знайдено!", + "Expand_Paradigms": "Словозміна", + "Collapse_Paradigms": "Приховати", + "Similar_To": "схоже на" +} diff --git a/src/strings/uzb.json b/src/strings/uzb.json index 5cbdabcae..80316a0cb 100644 --- a/src/strings/uzb.json +++ b/src/strings/uzb.json @@ -8,46 +8,46 @@ "uz", "uzb" ], - "completion": " 80% 91.22%", + "completion": " 70% 88.29%", "missing": [ "Apertium_Documentation", + "Collapse_Paradigms", + "Dictionary", + "Expand_Paradigms", "Install_Apertium", "Install_Apertium_Para", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", + "Search", + "Similar_To", "Supported_Formats", "Translate_Webpage", - "Translation_Help" + "Translation_Help", + "Type_A_Word" ] }, "title": "Apertium | Tekin, ochiq kodli mashina tarjima platformasi", "tagline": "Tekin, ochiq kodli mashina tarjima platformasi", "description": "Apertium - qoidaga asoslangan mashina tarjima platformasi. Bu dastur tekin bo‘lib GNU General Public License shartlari asosida chop etilgan.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "Tarjima", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "Tarjima qilish", "Detect_Language": "Tilni aniqlash", "detected": "aniqlandi", "Instant_Translation": "Tez tarjima", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", "Translate_Document": "Hujjatni tarjima qilish", "Drop_Document": "Hujjatni tashlash", "Not_Available": "Tarjima hali mavjud emas!", "File_Too_Large": "Fayl juda katta!", "Cancel": "Bekor qilish", "Format_Not_Supported": "Format qo‘llanilmaydi!", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "Morfologik tahlil", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "Tahlil qilish", "Morphological_Generation": "Morfologik generator", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "Ishlab chiqarish", "Spell_Checker": "Imlo tekshiruvchi", "APy_Sandbox": "APy qumdon", @@ -66,14 +66,11 @@ "About": "Haqida", "Download": "Yuklab olish", "Contact": "Aloqa qilish", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "Hujjatlar", "About_Apertium": "Apertium haqida", "What_Is_Apertium": "

      Apertium dastlab bog‘liq tillar juftligiga mo‘ljallangan, lekin keyinchalik bir-biridan ayiriluvchi tillar juftligi (mas. Inglizcha - Katalancha) bilan ishlashga moslashtirilgan tekin, ochiq kodli mashina tarjima platformasidir. Platforma quyidagilarni ta‘minlaydi:

      1. biror bir tilga bog‘liq bo‘lmagan mashina tarjima motori
      2. berilgan til juftligi uchun mashina tarjimasi tizimini yaratish uchun kerakli lingvistik ma‘lumotlarni boshqaruvchi asboblar va
      3. oshib borayotgan tillar juftligi uchun lingvistik ma‘lumotlar.

      Apertium yangi tuzuvchilarni xush ko‘radi: agar motorni yoki asboblarni yaxshilay olaman deb o‘ylasangiz, yoki biz uchun lingvistik ma‘lumotlarni rivojlantirib bilsangiz, bizga murojaat qilishdan tortinmang.

      ", "Documentation_Para": "Hujjatlarni Vikimizning Hujjatlar ost-sahifasida topshingiz mumkin. Biz turli xil konferensiya ilmiy hujjatlari va jurnal maqolalarini chop etganmiz. Ularning ro‘yxatini Vikining Nashrlar sahifasida topishingiz mumkin.", "Apertium_Downloads": "Apertium Ko‘chirmalari", "Downloads_Para": "Apertium asboblar qutisi va til juftligi ma‘lumotlarining ushbu versiyalari GitHub sahifasida mavjud. Apertiumni barcha muhim platformalarda o‘rnatish ko‘rsatmalari Vikining O‘rnatish sahifasida berilgan.", - "Contact_Para": "

      Chat (IRC) kanali

      irc.oftc.net dagi Apertiumning foydalanuvchilari va tuzuvchilari uchrashadigan #apertium IRC kanalimizga ulanish orqali biz bilgan tezda bog‘lanishingiz mumkin. Bu uchun sizga IRC mijozi shart emas; OFTC veb chatinini ishlatishingiz mumkin.

      Tarqatish ro‘yxatlari

      Uzunroq taklif yoki muammolarni yozishingiz, shu bilan birga umumiy Apertium muhokamalarni kuzatishingiz mumkin bo‘lgan apertium-stuff tarqatish ro‘yxatiga ham a‘zo bo‘ling.

      Murojaat qilish

      Xato topsangiz, bizni biror loyiha ustida ishlashimizni xoxlasangiz, yoki yordam bermoqchi bo‘lsangiz bizga apertium-contact tarqatish ro‘yxati orqali bizga murojaat qilishdan tortinmang

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "Contact_Para": "

      Chat (IRC) kanali

      irc.oftc.net dagi Apertiumning foydalanuvchilari va tuzuvchilari uchrashadigan #apertium IRC kanalimizga ulanish orqali biz bilgan tezda bog‘lanishingiz mumkin. Bu uchun sizga IRC mijozi shart emas; OFTC veb chatinini ishlatishingiz mumkin.

      Tarqatish ro‘yxatlari

      Uzunroq taklif yoki muammolarni yozishingiz, shu bilan birga umumiy Apertium muhokamalarni kuzatishingiz mumkin bo‘lgan apertium-stuff tarqatish ro‘yxatiga ham a‘zo bo‘ling.

      Murojaat qilish

      Xato topsangiz, bizni biror loyiha ustida ishlashimizni xoxlasangiz, yoki yordam bermoqchi bo‘lsangiz bizga apertium-contact tarqatish ro‘yxati orqali bizga murojaat qilishdan tortinmang

      " } diff --git a/src/strings/zho.json b/src/strings/zho.json index ecd0f21b0..0122a438c 100644 --- a/src/strings/zho.json +++ b/src/strings/zho.json @@ -9,7 +9,7 @@ "zh", "zho" ], - "completion": " 43% 3.88%", + "completion": " 38% 3.75%", "missing": [ "APy_Request", "APy_Sandbox", @@ -17,11 +17,14 @@ "Apertium_Documentation", "Apertium_Downloads", "Cancel", + "Collapse_Paradigms", "Contact_Para", + "Dictionary", "Documentation_Para", "Downloads_Para", "Drop_Document", "Enable_JS_Warning", + "Expand_Paradigms", "File_Too_Large", "Format_Not_Supported", "Input_Text", @@ -29,72 +32,46 @@ "Install_Apertium_Para", "Maintainer", "Mark_Unknown_Words", + "More_Languages", "Morphological_Analysis_Help", "Morphological_Generation_Help", "Multi_Step_Translation", + "No_results_found", "Norm_Preferences", "Not_Found_Error", + "Search", + "Similar_To", "Supported_Formats", "Translate_Document", "Translate_Webpage", "Translation_Help", + "Type_A_Word", "What_Is_Apertium", "description", "tagline", "title" ] }, - "title": "%%UNAVAILABLE%% Apertium | A free/open-source machine translation platform", - "tagline": "%%UNAVAILABLE%% A free/open-source machine translation platform", - "description": "%%UNAVAILABLE%% Apertium is a rule-based machine translation platform. It is free software and released under the terms of the GNU General Public License.", - "Apertium_Documentation": "%%UNAVAILABLE%% Apertium Documentation", "Translation": "翻译", - "Translation_Help": "%%UNAVAILABLE%% Enter text or URL to translate.", "Translate": "翻译", "Detect_Language": "自动检测", "detected": "检测到的语言", "Instant_Translation": "实时翻译", - "Mark_Unknown_Words": "%%UNAVAILABLE%% Mark unknown words", - "Multi_Step_Translation": "%%UNAVAILABLE%% Multi-step translation (experimental)", - "Translate_Document": "%%UNAVAILABLE%% Translate a document", - "Drop_Document": "%%UNAVAILABLE%% Drop a document", "Not_Available": "翻译还没有完成!", - "File_Too_Large": "%%UNAVAILABLE%% File is too large!", - "Cancel": "%%UNAVAILABLE%% Cancel", - "Format_Not_Supported": "%%UNAVAILABLE%% Format not supported", - "Translate_Webpage": "%%UNAVAILABLE%% Translate a webpage", - "Supported_Formats": "%%UNAVAILABLE%% Supported formats: .txt, .rtf, .odp, .ods, .odt (LibreOffice/OpenOffice), .xlsx, .pptx, .docx (Microsoft Office 2003 and newer).
      Word 97 .doc files and pdf's are not supported.", "Morphological_Analysis": "形态分析", - "Morphological_Analysis_Help": "%%UNAVAILABLE%% Enter text for morphological analysis.", "Analyze": "分析", "Morphological_Generation": "形态生成", - "Morphological_Generation_Help": "%%UNAVAILABLE%% Enter morphological forms that you would like generated into text.", "Generate": "生成", "Spell_Checker": "拼写检查器", - "APy_Sandbox": "%%UNAVAILABLE%% APy sandbox", - "APy_Sandbox_Help": "%%UNAVAILABLE%% Send arbitrary requests", - "APy_Request": "%%UNAVAILABLE%% APy Request", "Request": "请求", "Language": "语言", - "Input_Text": "%%UNAVAILABLE%% Input text", "Notice_Mistake": "发现了任何错误?", "Help_Improve": "帮助我们改进Apertium!", "Contact_Us": "如果您发现了任何错误,希望我们work on a specific project,或者想要为Apertium做出贡献,请通知我们。", - "Maintainer": "%%UNAVAILABLE%% This website is maintained by {{maintainer}}.", "About_Title": "关于这个网站", - "Enable_JS_Warning": "%%UNAVAILABLE%% This site only works with JavaScript enabled, if you cannot enable Javascript, then try the translators at Prompsit.", - "Not_Found_Error": "%%UNAVAILABLE%% 404 Error: Sorry, that page doesn't exist anymore!", "About": "关于Apertium", "Download": "下载", "Contact": "联络", - "Norm_Preferences": "%%UNAVAILABLE%% Style preferences", "Documentation": "文档", - "About_Apertium": "关于Apertium", - "What_Is_Apertium": "%%UNAVAILABLE%%

      Apertium is a free/open-source machine translation platform, initially aimed at related-language pairs but expanded to deal with more divergent language pairs (such as English-Catalan). The platform provides

      1. a language-independent machine translation engine
      2. tools to manage the linguistic data necessary to build a machine translation system for a given language pair and
      3. linguistic data for a growing number of language pairs.

      Apertium welcomes new developers: if you think you can improve the engine or the tools, or develop linguistic data for us, do not hesitate to contact us.

      ", - "Documentation_Para": "%%UNAVAILABLE%% Documentation can be found on our Wiki under the Documentation sub-page. We have published various conference papers and journal articles, a list of which may be found on the Wiki under Publications.", - "Apertium_Downloads": "%%UNAVAILABLE%% Apertium Downloads", - "Downloads_Para": "%%UNAVAILABLE%% Current versions of the Apertium toolbox as well as of language-pair data are available from the GitHub page. Installation instructions for Apertium on all major platforms are provided on the Wiki's Installation page.", - "Contact_Para": "%%UNAVAILABLE%%

      IRC channel

      The quickest way to contact us is by joining our IRC channel, #apertium at irc.oftc.net, where users and developers of Apertium meet. You don't need an IRC client; you can use OFTC webchat.

      Mailing list

      Also, subscribe to the apertium-stuff mailing list, where you can post longer proposals or issues, as well as follow general Apertium discussions.

      Contact

      Feel free to contact us via the apertium-contact mailing list if you find a mistake, there's a project you would like to see us work on, or you would like to help out.

      ", - "Install_Apertium": "%%UNAVAILABLE%% Install Apertium", - "Install_Apertium_Para": "%%UNAVAILABLE%% Are you experiencing slow responses? Our servers might be overloaded. Learn how to install Apertium locally." + "About_Apertium": "关于Apertium" } diff --git a/src/types.ts b/src/types.ts index b6caa1c65..af49fce37 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,6 +5,7 @@ export enum Mode { Analysis = 'analysis', Generation = 'generation', Sandbox = 'sandbox', + Dictionary = 'dictionary', // dict } export type Config = { diff --git a/src/util/localization.ts b/src/util/localization.ts index cdc3178c7..4ca073b3c 100644 --- a/src/util/localization.ts +++ b/src/util/localization.ts @@ -66,6 +66,25 @@ export const useLocalization = (): { t: (id: string) => string; tLang: (code: st return React.useMemo(() => ({ t: t(locale, strings), tLang: tLang(locale, strings) }), [strings, locale]); }; +// for pos localization +export const useLocalizationPOS = (): { + locale: string; + t: (id: string) => string; + tLang: (code: string) => string; +} => { + const strings = React.useContext(StringsContext); + const locale = React.useContext(LocaleContext); + + return React.useMemo( + () => ({ + locale, + t: t(locale, strings), + tLang: tLang(locale, strings), + }), + [strings, locale] + ); +}; + export const validLocale = (code: string): boolean => { const alpha3Code = toAlpha3Code(code); return alpha3Code != null && alpha3Code in locales; diff --git a/src/util/posLocalization.ts b/src/util/posLocalization.ts new file mode 100644 index 000000000..b0a54b3fd --- /dev/null +++ b/src/util/posLocalization.ts @@ -0,0 +1,22 @@ +import eng from '../strings/pos/eng.json'; +import ukr from '../strings/pos/ukr.json'; +import rus from '../strings/pos/rus.json'; +import deu from '../strings/pos/deu.json'; + +type PosMap = Record>; + +const posMap: PosMap = { + eng, + ukr, + rus, + deu, +}; + +export function getPosTag(locale: string, tagKey: string): string { + const code = locale.length === 2 ? locale + 'g' : locale; + const map = posMap[code]; + if (map && Object.prototype.hasOwnProperty.call(map, tagKey)) { + return map[tagKey]; + } + return tagKey; +}