i18n infopages
This commit is contained in:
parent
ae11c80051
commit
d1a576da3c
@ -31,7 +31,8 @@ export default defineConfig({
|
||||
assetsDir: './assets',
|
||||
modulePreload: { polyfill: false },
|
||||
commonjsOptions: { esmExternals: true },
|
||||
assetsInlineLimit: 1024
|
||||
assetsInlineLimit: 1024,
|
||||
sourcemap: false,
|
||||
},
|
||||
ssr: {
|
||||
external: ['cacache', 'glob', 'xlsx', 'sharp', '@polymech/kbot-d']
|
||||
|
||||
@ -1,57 +1,57 @@
|
||||
// @ts-check
|
||||
|
||||
const colours = {
|
||||
reset: "\x1b[0m",
|
||||
bright: "\x1b[1m",
|
||||
dim: "\x1b[2m",
|
||||
underscore: "\x1b[4m",
|
||||
blink: "\x1b[5m",
|
||||
reverse: "\x1b[7m",
|
||||
hidden: "\x1b[8m",
|
||||
|
||||
fg: {
|
||||
black: "\x1b[30m",
|
||||
red: "\x1b[31m",
|
||||
green: "\x1b[32m",
|
||||
yellow: "\x1b[33m",
|
||||
blue: "\x1b[34m",
|
||||
magenta: "\x1b[35m",
|
||||
cyan: "\x1b[36m",
|
||||
white: "\x1b[37m",
|
||||
},
|
||||
|
||||
bg: {
|
||||
black: "\x1b[40m",
|
||||
red: "\x1b[41m",
|
||||
green: "\x1b[42m",
|
||||
yellow: "\x1b[43m",
|
||||
blue: "\x1b[44m",
|
||||
magenta: "\x1b[45m",
|
||||
cyan: "\x1b[46m",
|
||||
white: "\x1b[47m",
|
||||
},
|
||||
};
|
||||
|
||||
export default function printWarning({
|
||||
key = "",
|
||||
type = "",
|
||||
message = "",
|
||||
element = "",
|
||||
}) {
|
||||
const flag =
|
||||
colours.bright + colours.fg.cyan + "[astro-imagetools]" + colours.reset;
|
||||
|
||||
const keyLog = key
|
||||
? " " + colours.bg.yellow + ` ${key} ` + colours.reset
|
||||
: "";
|
||||
|
||||
const messageLog =
|
||||
colours.fg.yellow +
|
||||
(message ||
|
||||
(!element
|
||||
? `is not a valid ${type} Config Option`
|
||||
: `can't be defined inside attributes.${element}`)) +
|
||||
colours.reset;
|
||||
|
||||
console.log(flag + keyLog, messageLog);
|
||||
}
|
||||
// @ts-check
|
||||
|
||||
const colours = {
|
||||
reset: "\x1b[0m",
|
||||
bright: "\x1b[1m",
|
||||
dim: "\x1b[2m",
|
||||
underscore: "\x1b[4m",
|
||||
blink: "\x1b[5m",
|
||||
reverse: "\x1b[7m",
|
||||
hidden: "\x1b[8m",
|
||||
|
||||
fg: {
|
||||
black: "\x1b[30m",
|
||||
red: "\x1b[31m",
|
||||
green: "\x1b[32m",
|
||||
yellow: "\x1b[33m",
|
||||
blue: "\x1b[34m",
|
||||
magenta: "\x1b[35m",
|
||||
cyan: "\x1b[36m",
|
||||
white: "\x1b[37m",
|
||||
},
|
||||
|
||||
bg: {
|
||||
black: "\x1b[40m",
|
||||
red: "\x1b[41m",
|
||||
green: "\x1b[42m",
|
||||
yellow: "\x1b[43m",
|
||||
blue: "\x1b[44m",
|
||||
magenta: "\x1b[45m",
|
||||
cyan: "\x1b[46m",
|
||||
white: "\x1b[47m",
|
||||
},
|
||||
};
|
||||
|
||||
export default function printWarning({
|
||||
key = "",
|
||||
type = "",
|
||||
message = "",
|
||||
element = "",
|
||||
}) {
|
||||
const flag =
|
||||
colours.bright + colours.fg.cyan + "[astro-imagetools]" + colours.reset;
|
||||
|
||||
const keyLog = key
|
||||
? " " + colours.bg.yellow + ` ${key} ` + colours.reset
|
||||
: "";
|
||||
|
||||
const messageLog =
|
||||
colours.fg.yellow +
|
||||
(message ||
|
||||
(!element
|
||||
? `is not a valid ${type} Config Option`
|
||||
: `can't be defined inside attributes.${element}`)) +
|
||||
colours.reset;
|
||||
|
||||
//console.log(flag + keyLog, messageLog);
|
||||
}
|
||||
|
||||
@ -18,14 +18,6 @@
|
||||
}
|
||||
},
|
||||
"footer_left": [
|
||||
{
|
||||
"href": "/rss.xml",
|
||||
"text": "RSS"
|
||||
},
|
||||
{
|
||||
"href": "/helpcenter/home",
|
||||
"text": "Help"
|
||||
},
|
||||
{
|
||||
"href": "/infopages/privacy",
|
||||
"text": "Privacy"
|
||||
@ -33,10 +25,6 @@
|
||||
{
|
||||
"href": "/infopages/contact",
|
||||
"text": "Contact"
|
||||
},
|
||||
{
|
||||
"href": "/infopages/about",
|
||||
"text": "About us"
|
||||
}
|
||||
],
|
||||
"footer_right": [
|
||||
|
||||
140
src/base/i18n.ts
140
src/base/i18n.ts
@ -1,68 +1,72 @@
|
||||
import * as path from 'path'
|
||||
import { resolve } from '@polymech/commons'
|
||||
import { sync as exists } from '@polymech/fs/exists'
|
||||
|
||||
import type { IOptions } from '@polymech/i18n'
|
||||
import { CONFIG_DEFAULT } from '@polymech/commons'
|
||||
import { I18N_ASSET_PATH, I18N_CACHE, I18N_SOURCE_LANGUAGE,
|
||||
PRODUCT_DIR, PRODUCT_SPECS,
|
||||
RETAIL_LOG_LEVEL_I18N_PRODUCT_ASSETS } from '@/app/config.js'
|
||||
|
||||
import { translateXLS } from '@polymech/i18n/translate_xls'
|
||||
import { I18N_STORE, OSR_ROOT } from 'config/config.js'
|
||||
import { translateText } from '@polymech/i18n/translate_text'
|
||||
import { logger } from './index.js'
|
||||
|
||||
export type { IOptions } from '@polymech/i18n'
|
||||
|
||||
export const translate = async (text: string, srcLanguage = 'en', targetLanguage, opts = {}) => {
|
||||
if (!targetLanguage) {
|
||||
return text
|
||||
}
|
||||
try {
|
||||
const store = I18N_STORE(OSR_ROOT(), targetLanguage)
|
||||
let translation = text
|
||||
translation = await translateText(text, srcLanguage, targetLanguage, {
|
||||
store,
|
||||
...opts
|
||||
})
|
||||
return translation
|
||||
} catch (e) {
|
||||
logger.error(`Failed to translate text: ${text} from ${srcLanguage} to ${targetLanguage} : ${e.message}`, e)
|
||||
}
|
||||
return text
|
||||
}
|
||||
export const translateSheets = async (product, language) => {
|
||||
const config: any = CONFIG_DEFAULT()
|
||||
if (language === I18N_SOURCE_LANGUAGE) {
|
||||
return
|
||||
}
|
||||
const i18nOptions: IOptions = {
|
||||
srcLang: I18N_SOURCE_LANGUAGE,
|
||||
dstLang: language,
|
||||
src: PRODUCT_SPECS(product),
|
||||
store: I18N_STORE(OSR_ROOT(), language),
|
||||
dst: I18N_ASSET_PATH,
|
||||
query: "$[*][0,1,2,3]",
|
||||
cache: I18N_CACHE,
|
||||
api_key: config.deepl.auth_key,
|
||||
logLevel: RETAIL_LOG_LEVEL_I18N_PRODUCT_ASSETS
|
||||
}
|
||||
const src = `${PRODUCT_SPECS(product)}`
|
||||
const srcParts = path.parse(src)
|
||||
const dst = path.resolve(resolve(I18N_ASSET_PATH, false, {
|
||||
SRC_DIR: srcParts.dir,
|
||||
SRC_NAME: srcParts.name,
|
||||
SRC_EXT: srcParts.ext,
|
||||
DST_LANG: language
|
||||
}))
|
||||
if (I18N_CACHE && exists(dst)) {
|
||||
return dst
|
||||
}
|
||||
logger.debug(`Translate assets ${src} to ${language}`)
|
||||
try {
|
||||
return await translateXLS(path.resolve(src), dst, i18nOptions)
|
||||
} catch (e) {
|
||||
logger.error(`Failed to translate assets ${src} to ${language}`, e.message, e)
|
||||
}
|
||||
}
|
||||
import * as path from 'path'
|
||||
import { resolve } from '@polymech/commons'
|
||||
import { sync as exists } from '@polymech/fs/exists'
|
||||
|
||||
import type { IOptions } from '@polymech/i18n'
|
||||
import { CONFIG_DEFAULT } from '@polymech/commons'
|
||||
import {
|
||||
I18N_ASSET_PATH,
|
||||
I18N_CACHE,
|
||||
I18N_SOURCE_LANGUAGE,
|
||||
PRODUCT_SPECS,
|
||||
RETAIL_LOG_LEVEL_I18N_PRODUCT_ASSETS
|
||||
} from '@/app/config.js'
|
||||
|
||||
import { translateXLS } from '@polymech/i18n/translate_xls'
|
||||
import { I18N_STORE, OSR_ROOT } from 'config/config.js'
|
||||
import { translateText } from '@polymech/i18n/translate_text'
|
||||
import { logger } from './index.js'
|
||||
|
||||
export type { IOptions } from '@polymech/i18n'
|
||||
|
||||
export const translate = async (text: string, srcLanguage = 'en', targetLanguage, opts = {}) => {
|
||||
if (!targetLanguage) {
|
||||
return text
|
||||
}
|
||||
try {
|
||||
const store = I18N_STORE(OSR_ROOT(), targetLanguage)
|
||||
let translation = text
|
||||
translation = await translateText(text, srcLanguage, targetLanguage, {
|
||||
store,
|
||||
...opts
|
||||
})
|
||||
return translation
|
||||
} catch (e) {
|
||||
logger.error(`Failed to translate text: ${text} from ${srcLanguage} to ${targetLanguage} : ${e.message}`, e)
|
||||
}
|
||||
return text
|
||||
}
|
||||
export const translateSheets = async (product, language) => {
|
||||
const config: any = CONFIG_DEFAULT()
|
||||
if (language === I18N_SOURCE_LANGUAGE) {
|
||||
return
|
||||
}
|
||||
const i18nOptions: IOptions = {
|
||||
srcLang: I18N_SOURCE_LANGUAGE,
|
||||
dstLang: language,
|
||||
src: PRODUCT_SPECS(product),
|
||||
store: I18N_STORE(OSR_ROOT(), language),
|
||||
dst: I18N_ASSET_PATH,
|
||||
query: "$[*][0,1,2,3]",
|
||||
cache: I18N_CACHE,
|
||||
api_key: config.deepl.auth_key,
|
||||
logLevel: RETAIL_LOG_LEVEL_I18N_PRODUCT_ASSETS
|
||||
}
|
||||
const src = `${PRODUCT_SPECS(product)}`
|
||||
const srcParts = path.parse(src)
|
||||
const dst = path.resolve(resolve(I18N_ASSET_PATH, false, {
|
||||
SRC_DIR: srcParts.dir,
|
||||
SRC_NAME: srcParts.name,
|
||||
SRC_EXT: srcParts.ext,
|
||||
DST_LANG: language
|
||||
}))
|
||||
if (I18N_CACHE && exists(dst)) {
|
||||
return dst
|
||||
}
|
||||
logger.debug(`Translate assets ${src} to ${language}`)
|
||||
try {
|
||||
return await translateXLS(path.resolve(src), dst, i18nOptions)
|
||||
} catch (e) {
|
||||
logger.error(`Failed to translate assets ${src} to ${language}`, e.message, e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,69 +1,73 @@
|
||||
import { unified } from "unified";
|
||||
import remarkParse from "remark-parse";
|
||||
import remarkRehype from "remark-rehype";
|
||||
import rehypeStringify from "rehype-stringify";
|
||||
import { createComponent } from "astro/runtime/server/astro-component.js";
|
||||
import { renderTemplate, unescapeHTML } from "astro/runtime/server/index.js";
|
||||
|
||||
import { findUp } from 'find-up'
|
||||
import { createLogger } from '@polymech/log'
|
||||
import { parse, IProfile } from '@polymech/commons/profile'
|
||||
import { renderMarkup } from "@/model/component.js";
|
||||
import {
|
||||
LOGGING_NAMESPACE,
|
||||
OSRL_ENV,
|
||||
OSRL_PRODUCT_PROFILE,
|
||||
PRODUCT_ROOT,
|
||||
I18N_SOURCE_LANGUAGE
|
||||
} from 'config/config.js'
|
||||
|
||||
import { translate } from "@/base/i18n.js"
|
||||
|
||||
export const logger = createLogger(LOGGING_NAMESPACE)
|
||||
export const boot = () => logger.info('Astro is booting up')
|
||||
export const env = (item_rel: string = ""): IProfile => {
|
||||
let default_profile: IProfile = {
|
||||
includes: [],
|
||||
variables: {
|
||||
root: PRODUCT_ROOT(),
|
||||
product: item_rel,
|
||||
product_rel: item_rel,
|
||||
}
|
||||
}
|
||||
default_profile = parse(OSRL_PRODUCT_PROFILE, default_profile, { env: OSRL_ENV })
|
||||
return default_profile;
|
||||
}
|
||||
export const render = async (string) => {
|
||||
const html = `${unescapeHTML(string)}`
|
||||
return createComponent(() => renderTemplate(html as any, []))
|
||||
}
|
||||
export const component = async (str: string = "", locale, data = {}) => {
|
||||
const content = await translate(
|
||||
(str || "").trim(),
|
||||
I18N_SOURCE_LANGUAGE,
|
||||
locale
|
||||
)
|
||||
const markup = ((await renderMarkup(content, data)) as any) || { html: "" }
|
||||
return await render(markup.html)
|
||||
}
|
||||
export const item_defaults = async (itemDir) => {
|
||||
return await findUp('defaults.json', {
|
||||
stopAt: PRODUCT_ROOT(),
|
||||
cwd: itemDir
|
||||
})
|
||||
}
|
||||
|
||||
export async function markdownToHtml(markdown: string): Promise<string> {
|
||||
const result = await unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkRehype)
|
||||
.use(rehypeStringify)
|
||||
.process(markdown);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
export async function createMarkdownComponent(markdown: string) {
|
||||
const html = unescapeHTML(await markdownToHtml(markdown));
|
||||
return createComponent(() => renderTemplate(html as any, []));
|
||||
import { unified } from "unified";
|
||||
import remarkParse from "remark-parse";
|
||||
import remarkRehype from "remark-rehype";
|
||||
import rehypeStringify from "rehype-stringify";
|
||||
import { createComponent } from "astro/runtime/server/astro-component.js";
|
||||
import { renderTemplate, unescapeHTML } from "astro/runtime/server/index.js";
|
||||
|
||||
import { findUp } from 'find-up'
|
||||
import { createLogger } from '@polymech/log'
|
||||
import { parse, IProfile } from '@polymech/commons/profile'
|
||||
import { renderMarkup } from "@/model/component.js";
|
||||
import {
|
||||
LOGGING_NAMESPACE,
|
||||
OSRL_ENV,
|
||||
OSRL_PRODUCT_PROFILE,
|
||||
PRODUCT_ROOT,
|
||||
I18N_SOURCE_LANGUAGE
|
||||
} from 'config/config.js'
|
||||
|
||||
import { translate } from "@/base/i18n.js"
|
||||
|
||||
export const logger = createLogger(LOGGING_NAMESPACE)
|
||||
export const boot = () => logger.info('Astro is booting up')
|
||||
export const env = (item_rel: string = ""): IProfile => {
|
||||
let default_profile: IProfile = {
|
||||
includes: [],
|
||||
variables: {
|
||||
root: PRODUCT_ROOT(),
|
||||
product: item_rel,
|
||||
product_rel: item_rel,
|
||||
}
|
||||
}
|
||||
default_profile = parse(OSRL_PRODUCT_PROFILE, default_profile, { env: OSRL_ENV })
|
||||
return default_profile;
|
||||
}
|
||||
export const render = async (string) => {
|
||||
const html = `${unescapeHTML(string)}`
|
||||
return createComponent(() => renderTemplate(html as any, []))
|
||||
}
|
||||
export const component = async (str: string = "", locale, data = {}) => {
|
||||
const content = await translate(
|
||||
(str || "").trim(),
|
||||
I18N_SOURCE_LANGUAGE,
|
||||
locale
|
||||
)
|
||||
const markup = ((await renderMarkup(content, data)) as any) || { html: "" }
|
||||
return await render(markup.html)
|
||||
}
|
||||
export const item_defaults = async (itemDir) => {
|
||||
return await findUp('defaults.json', {
|
||||
stopAt: PRODUCT_ROOT(),
|
||||
cwd: itemDir
|
||||
})
|
||||
}
|
||||
|
||||
export async function markdownToHtml(markdown: string): Promise<string> {
|
||||
const result = await unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkRehype)
|
||||
.use(rehypeStringify)
|
||||
.process(markdown);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
export async function createMarkdownComponent(markdown: string) {
|
||||
const html = unescapeHTML(await markdownToHtml(markdown));
|
||||
return createComponent(() => renderTemplate(html as any, []));
|
||||
}
|
||||
|
||||
export async function createHTMLComponent(html: string) {
|
||||
return createComponent(() => renderTemplate(unescapeHTML(html) as any, []))
|
||||
}
|
||||
@ -87,7 +87,6 @@ const locale = Astro.currentLocale || "en";
|
||||
format="avif"
|
||||
placeholder="blurred"
|
||||
breakpoints={[200,300,500]}
|
||||
sizes="(max-width: 80px) 80px, 80vw"
|
||||
fadeInTransition={{
|
||||
delay: "0.5s",
|
||||
duration: "2.5s",
|
||||
|
||||
@ -15,7 +15,7 @@ const {
|
||||
|
||||
const content = await Astro.slots.render('default')
|
||||
const translatedText = await translate(content, I18N_SOURCE_LANGUAGE, language, rest)
|
||||
console.log('translatedText', translatedText)
|
||||
|
||||
---
|
||||
<div data-widget="polymech.i18n" class={clazz}>
|
||||
{translatedText}
|
||||
|
||||
@ -3,11 +3,10 @@ import BaseLayout from "./BaseLayout.astro";
|
||||
import Wrapper from "@/components/containers/Wrapper.astro";
|
||||
import { I18N_SOURCE_LANGUAGE } from "config/config.js"
|
||||
import { translate } from '@/base/i18n.js'
|
||||
import { component } from '@/base/index.js'
|
||||
const { frontmatter } = Astro.props;
|
||||
import { createHTMLComponent } from '@/base/index.js'
|
||||
const content = await Astro.slots.render('default')
|
||||
const translatedText = await translate(content, I18N_SOURCE_LANGUAGE, Astro.currentLocale)
|
||||
const Markup = await component(translatedText, Astro.currentLocale, frontmatter)
|
||||
const Markup = await createHTMLComponent(translatedText)
|
||||
---
|
||||
<BaseLayout>
|
||||
<Wrapper>
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
---
|
||||
import StoreLayout from '@/layouts/StoreLayout.astro'
|
||||
import { getCollection } from 'astro:content'
|
||||
import { LANGUAGES_PROD as LANGUAGES } from "config/config.js"
|
||||
import InfoPagesLayout from '@/layouts/InfoPagesLayout.astro';
|
||||
|
||||
Reference in New Issue
Block a user