Merge branch 'main' into TheDragonOfFlame-patch-1

This commit is contained in:
Jezza Hehn 2026-05-03 23:14:31 -04:00 committed by GitHub
commit 2452ad42cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 678 additions and 392 deletions

View file

@ -18,9 +18,8 @@
"axios": "^1.11.0",
"bulma": "^1.0.4",
"tailwindcss": "^4.1.6",
"vue": "^3.5.13",
"vue-i18n": "^11.1.3",
"vue-router": "^4.5.1"
"vue-router": "^5.0.4"
},
"devDependencies": {
"@eslint/js": "^9.39.2",
@ -34,10 +33,11 @@
"sass": "^1.87.0",
"typescript": "~5.8.3",
"typescript-eslint": "^8.55.0",
"unplugin-vue-router": "^0.12.0",
"unplugin-vue-router": "^0.19.2",
"vite": "^6.3.5",
"vue": "^3.5.32",
"vue-eslint-parser": "^10.2.0",
"vue-tsc": "^2.2.8"
"vue-tsc": "^3.2.6"
},
"packageManager": "pnpm@10.11.0"
}

View file

@ -0,0 +1,78 @@
localeName = "Español (Latinoamérica)"
vilanticLangs-viossa = "Viossa"
vilanticLangs-wodox = "Wodoch"
vilanticLangs-minemiaha = "Minemiaha"
navbar-whatIsViossa = "¿Qué es Viossa?"
navbar-resources = "Recursos"
navbar-kotoba = "Kotoba"
home-sections-whatIsViossa-title = "¿Qué es Viossa?"
home-sections-whatIsViossa-body = "Viossa es una lengua pidgin artificial que fue creada en comunidad para simular la formación de idiomas pidgin naturales. Viossa se caracteriza por no tener ningn estandár, por lo que cada hablante desarrolla su propio idiolecto. La pronunciación y la ortografía pueden variar mucho y cumplen un rol importante en la autoexpresión. Viossa se enseña y aprende únicamente por inmersión. Las traducciones están prohibidas en el proceso de aprendizaje."
home-sections-historyOfViossa-title = "Historia de Viossa"
home-sections-historyOfViossa-body = "Viossa nació como un grupo de Skype en 2014, el cual fue creado por miembros del subreddit r/conlangs como un experimento para simular la formación de un idioma pidgin. Un pidgin es una lengua simple que surge por medio del contacto entre grupos sin una lengua en común. A diferencia de la mayoría de pidgins, que están formados a partir de dos o tres lenguas contribuyentes, Viossa tiene raíces en un gran número de idiomas diversos. Esto se debe a que mucha gente alrededor del mundo se unió para aportar al vocabulario de Viossa."
home-sections-community-title = "Comunidad"
home-sections-community-body = "La diversidad cultural de sus miembros y la integración de tradiciones de muchas partes del mundo le dan a la comunidad de Viossa una riqueza y valor únicos. La filosofía de su enseñanza promueve la inmersión lingüística y se opone al prescriptivismo, lo que resulta en una cultura tan diversa como el idioma en sí y sus hablantes. Para muchos, sus idiolectos son fundamentales para su forma de expresarse y su identidad. La naturaleza particular de Viossa y la ausencia de significados rígidos en él lo hacen ideal para actividades creativas como escribir poemas o canciones."
home-images-viossaFlag-alt = "Bandera del idioma Viossa"
resources-title = "Recursos de aprendizaje"
resources-resources-discord-title = "Servidor de Discord"
resources-resources-discord-subtitle = "¡Aquí es donde ocurre la mayor parte de la acción! ¡Únetenos!"
resources-resources-discord-desc = "Viossa Diskordserver (VDS) fue fundado en 2016 como sucesor del chat original de Viossa en Skype. Desde entonces ha superado los 6.000 miembros. ¡Lee las reglas con ayuda de los botones y luego únete al servidor!"
resources-resources-discord-buttons-join-label = "Unirse"
resources-resources-discord-buttons-rules-label = "Reglas"
resources-images-discordLogo-alt = "Logo de Discord"
kotoba-title = "Búsqueda independiente de tropos"
kotoba-searchHelp = "Introduce un término abajo para buscar sin importar el tropos"
discord-rulesPage-title = "Las reglas del servidor de Discord"
discord-rulesPage-overview-title = "Descripción general"
discord-rulesPage-overview-help = "Haz click en cualquier regla para ver detalles."
discord-rulesPage-rules-noTranslation-overview-text = md "¡Nada de traducciones! No traduzcas nada de/a Viossa dentro del servidor a excepción de las Grandes Cuatro (¡puedes aprender sin ellas en modo difícil!)"
discord-rulesPage-rules-noTranslation-overview-subtext = md --
discord-rulesPage-rules-noTranslation-section-header = "Regla { $ruleNumber }: Nada de traducciones"
discord-rulesPage-rules-noTranslation-section-body = md
"No traducimos nada en la enseñanza y aprendizaje de Viossa. En cambio, utilizamos imágenes, diagramas, videollamadas y otros métodos para conectar las palabras con sus significados."
"Está permitido traducir las siguientes cuatro palabras en el servidor. Si quieres un reto más difícil, no reveles el texto:"
"*TODO - big 4*"
"Permitimos también, fuera del proceso de aprendizaje, las traducciones artísticas (como aquellas de canciones, libros o poemas) así como las académicas (como aquellas utilizadas en investigaciones formales). En ambos casos, estas excepciones dependen de que dichas traducciones sean presentadas en el lugar adecuado. Por favor pregúntanos si no tienes certeza de dónde ponerlas."
"Además, no intentes replicar ni compartir ningún material de aprendizaje basado en la traducción en el servidor, y tampoco convenzas a los demás miembros de hacer esto."
discord-rulesPage-rules-lfsv-overview-text = md "Si se entiende, es Viossa."
discord-rulesPage-rules-lfsv-overview-subtext = md --
discord-rulesPage-rules-lfsv-section-header = "Regla { $ruleNumber }: Si se entiende, es Viossa"
discord-rulesPage-rules-lfsv-section-body = md
"Lo único que se requiere para hablar Viossa es que los demás hablantes te entiendan. No hay formas correctas ni erróneas de hablar o escribir ni hay un estándar global."
"No obstante, Viossa es un proyecto colaborativo: los miembros deben procurar darse a entender por los demás y a su vez esforzarse para entender a otros."
discord-rulesPage-rules-viossaOnlyChats-overview-text = md "Sólo se puede hablar Viossa en los canales de la categoría Viossa Only (Sólo Viossa)"
discord-rulesPage-rules-viossaOnlyChats-overview-subtext = md --
discord-rulesPage-rules-viossaOnlyChats-section-header = "Regla { $ruleNumber }: Canales en Viossa Only (Sólo Viossa)"
discord-rulesPage-rules-viossaOnlyChats-section-body = md
"No se permiten otros idiomas en los canales de la categoría Viossa Only. Si tienes que guiar a alguien en el proceso de aprendizaje y no puedes hacerlo en Viossa, dirígete a **#meta**"
"Sin embargo, esto no quiere decir que no puedas usar Viossa en los demás canales. ¡Háblalo donde quieras!"
discord-rulesPage-rules-sfw-overview-text = md "Este servidor es SFW. Se prohíbe el contenido violento, gore o sexualmente explícito."
discord-rulesPage-rules-sfw-overview-subtext = md --
discord-rulesPage-rules-sfw-section-header = "Regla { $ruleNumber }: SFW"
discord-rulesPage-rules-sfw-section-body = md
"Si a un moderador no le gusta lo que mandaste, te lo va a informar; mira [la regla 6](internal.replace:#rule-6). Esto es un servidor público; piensa antes de enviar algo."
discord-rulesPage-rules-respectOthers-overview-text = md "No se permite el discurso de odio. Hay que respetarse unos a otros."
discord-rulesPage-rules-respectOthers-overview-subtext = md --
discord-rulesPage-rules-respectOthers-section-header = "Rule { $ruleNumber }: Trata a los demás con respeto"
discord-rulesPage-rules-respectOthers-section-body = md
"Hay que respetarse unos a otros. No son bienvenidos el discurso de odio, la discriminación ni el apoyo a la violencia dentro o fuera del servidor. Ésta es una comunidad internacional, amigable y LGBTQ+."
discord-rulesPage-rules-respectStaff-overview-text = md "Respeta las decisiones del staff (**@Yewald** y **@Yewaldnen**)."
discord-rulesPage-rules-respectStaff-overview-subtext = md --
discord-rulesPage-rules-respectStaff-section-header = "Regla { $ruleNumber }: Respeta las decisiones del staff"
discord-rulesPage-rules-respectStaff-section-body = md
"Los miembros del staff (los Yewald al igual que los Yewaldnen) tienen la última palabra y pueden kickear, banear o silenciar miembros o cambiar sus permisos de acceso para garantizar que este entorno se mantenga seguro y para priorizar la integridad de la comunidad de Viossa."
"Siempre se tendrán en cuenta las apelaciones y puedes mandar un MD a cualquier Yewald o abrir un ticket con este comando de YAGPDB /tickets si consideras que un moderador actuó de forma inapropiada."
"Si has sido baneado, habrá instrucciones para apelar esta sanción, pero reflexiona a profundidad sobre el motivo del baneo antes de apelarlo."
discord-rulesPage-rules-controversialTopics-overview-text = md "Las discusiones sobre temas controversiales (política, guerra, entre otros) deben ser dirigidas al canal **#polite**, el cual requiere el rol **@Ike** (que sólo es accesible para los **@Viossadjin** y **@mellandjin**) para ser visto."
discord-rulesPage-rules-controversialTopics-overview-subtext = md "**#feels-and-advice** es para hablar abiertamente de tus sentimientos, pero ponemos el límite en las ideaciones suicidas o violentas. Éstas son cadenas de pensamiento que deben ser manejadas por un terapeuta y no son chistes. No pertenecen aquí por su seriedad."
discord-rulesPage-rules-controversialTopics-section-header = "Regla { $ruleNumber }: #polite e ike"
discord-rulesPage-rules-controversialTopics-section-body = md
"La vida está llena de situaciones complicadas y todos tenemos la necesidad de hablar de ellas. La categoría ike brinda el acceso a un grupo opcional de canales donde se permiten las discusiones de temas pesados, sensibles y potencialmente polémicos con la condición de que los usuarios sean especialmente respetuosos entre sí durante dichas discusiones. Al aceptar el rol ike estás de acuerdo con esta regla y fomentas que los demás hagan lo mismo."
"# Desahogarse vs pedir ayuda"
"A veces uno quiere expresar sus problemas para ser visto y otras veces necesita ayuda para resolverlos. Si estás abierto a uno y no al otro, te sugerimos comunicar esto en la conversación para recibir el tipo de respuesta más adecuado para ti."
"# Violencia y autolesiones"
"A pesar de que se permite hablar de las autolesiones (con el uso apropiado y claro de advertencias de contenido), este servidor no es un recurso de emergencia para la salud mental y no sustituye la ayuda profesional. Pedirle consejos a otros para encontrar apoyo o recursos fuera del servidor está bien, pero pedirles que te tranquilicen en medio de una crisis es inapropiado."
"No debes usar este espacio para:"
"- expresar intenciones o deseos de lastimarte a ti mismo o a alguien más"
"- pedir que te ayuden a evitar lastimarte a ti mismo o a alguien más"
"Al cruzar estos límites estás pidiéndole a los miembros del servidor (incluyendo a los moderadores y al dueño) que cumplan un rol para el cual no han sido entrenados ni equipados. Bajo la discreción de los moderadores esto puede no ser tolerado y resultar en una advertencia, un tiempo fuera, la eliminación del rol **@ike** o la expulsión del servidor."
"Si tienes problemas con pensamientos de esta naturaleza, pero no estás en peligro inmediato, considera buscar asesoramiento. Si estás pasando por una crisis inmediata, llama a los servicios de emergencia locales o busca un número de emergencia adecuado para ti. Aquí hay una lista de recursos por país: [](external.new:https://findahelpline.com/)"

View file

@ -134,4 +134,10 @@ export const GREETINGS = [
author: "We",
lang: "viossa",
},
{
title: "Braatullaca viossa.net:an!",
subtitle: "Afto Zeplas viossja je !Braaleraca Viossa au nintendoca !",
author: "Lunakot",
lang: "viossa",
},
] as const satisfies Greeting[];

View file

@ -13,6 +13,7 @@ import vpVlFtlSrc from "@/assets/locale/vp_VL.ftl";
import wpVlFtlSrc from "@/assets/locale/wp_VL.ftl";
import type { FluentBundle } from "@fluent/bundle";
import { compileLocale } from "@/vi18n-lib/compile";
import type { ComputedRef } from "vue";
export const LOCALE_IDS = ["en-US", "vp-VL", "wp-VL"] as const;
@ -143,42 +144,71 @@ function deepReadonly<T>(value: T): DeepReadonly<T> {
return value as DeepReadonly<T>;
}
const DEFAULT_LOCALE_BUNDLE = unwrap(await loadLocale("en-US", enUsFtlSrc));
const DEFAULT_LOCALE = unwrap(
setupLocale(DEFAULT_LOCALE_ID, DEFAULT_LOCALE_BUNDLE, undefined),
);
interface I18n {
useLocale: (opt?: UseLocaleOptions) => ComputedRef<DeepReadonly<Locale>>;
}
const doItAllForLocale = async (
localeId: LocaleId,
localeFtlSrc: string,
): Promise<DeepReadonly<Locale>> =>
deepReadonly(
unwrap(
setupLocale(
localeId,
unwrap(await loadLocale(localeId, localeFtlSrc)),
{ bundle: DEFAULT_LOCALE_BUNDLE, locale: DEFAULT_LOCALE },
),
),
async function initI18n(): Promise<I18n> {
const defaultLocaleBundle = unwrap(await loadLocale("en-US", enUsFtlSrc));
const defaultLocale = unwrap(
setupLocale(DEFAULT_LOCALE_ID, defaultLocaleBundle, undefined),
);
const [vpVl, wpVl] = await Promise.all([
doItAllForLocale("vp-VL", vpVlFtlSrc),
doItAllForLocale("wp-VL", wpVlFtlSrc),
]);
const doItAllForLocale = async (
localeId: LocaleId,
localeFtlSrc: string,
): Promise<DeepReadonly<Locale>> =>
deepReadonly(
unwrap(
setupLocale(
localeId,
unwrap(await loadLocale(localeId, localeFtlSrc)),
{ bundle: defaultLocaleBundle, locale: defaultLocale },
),
),
);
const localeIdToLocale = {
"en-US": deepReadonly(DEFAULT_LOCALE),
"vp-VL": vpVl,
"wp-VL": wpVl,
} as const satisfies Record<LocaleId, DeepReadonly<Locale>>;
const [vpVl, wpVl] = await Promise.all([
doItAllForLocale("vp-VL", vpVlFtlSrc),
doItAllForLocale("wp-VL", wpVlFtlSrc),
]);
const localeIdToLocale = {
"en-US": deepReadonly(defaultLocale),
"vp-VL": vpVl,
"wp-VL": wpVl,
} as const satisfies Record<LocaleId, DeepReadonly<Locale>>;
const useLocale = (opt: UseLocaleOptions = {}) =>
computed<DeepReadonly<Locale>>(() => {
const localLocaleId = opt.locale ?? localeId.value;
return localeIdToLocale[localLocaleId];
});
return { useLocale };
}
export interface UseLocaleOptions {
locale?: LocaleId;
}
export const useLocale = (opt: UseLocaleOptions = {}) =>
computed<DeepReadonly<Locale>>(() => {
const localLocaleId = opt.locale ?? localeId.value;
return localeIdToLocale[localLocaleId];
});
const initI18nPromise = initI18n();
let i18n: I18n | null = null;
initI18nPromise.then((x) => {
i18n = x;
});
export const onI18nInit = (f: () => void) => {
initI18nPromise.then(f);
};
export const useLocale = (
opt: UseLocaleOptions = {},
): ComputedRef<DeepReadonly<Locale>> => {
if (i18n === null) {
throw new Error("Cannot use i18n before initialized!");
}
return i18n.useLocale(opt);
};

View file

@ -1,5 +1,8 @@
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import { onI18nInit } from "./i18n";
createApp(App).use(router).mount("#app");
onI18nInit(() => {
createApp(App).use(router).mount("#app");
});

View file

@ -1,10 +1,15 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
// noinspection ES6UnusedImports
// Generated by unplugin-vue-router. !! DO NOT MODIFY THIS FILE !!
// It's recommended to commit this file.
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.
declare module 'vue-router/auto-resolver' {
export type ParamParserCustom = never
}
declare module 'vue-router/auto-routes' {
import type {
RouteRecordInfo,
@ -18,9 +23,81 @@ declare module 'vue-router/auto-routes' {
* Route name map generated by unplugin-vue-router
*/
export interface RouteNamedMap {
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
'/discord/rules': RouteRecordInfo<'/discord/rules', '/discord/rules', Record<never, never>, Record<never, never>>,
'/kotoba': RouteRecordInfo<'/kotoba', '/kotoba', Record<never, never>, Record<never, never>>,
'/resources': RouteRecordInfo<'/resources', '/resources', Record<never, never>, Record<never, never>>,
'/': RouteRecordInfo<
'/',
'/',
Record<never, never>,
Record<never, never>,
| never
>,
'/discord/rules': RouteRecordInfo<
'/discord/rules',
'/discord/rules',
Record<never, never>,
Record<never, never>,
| never
>,
'/kotoba': RouteRecordInfo<
'/kotoba',
'/kotoba',
Record<never, never>,
Record<never, never>,
| never
>,
'/resources': RouteRecordInfo<
'/resources',
'/resources',
Record<never, never>,
Record<never, never>,
| never
>,
}
/**
* Route file to route info map by unplugin-vue-router.
* Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
*
* Each key is a file path relative to the project root with 2 properties:
* - routes: union of route names of the possible routes when in this page (passed to useRoute<...>())
* - views: names of nested views (can be passed to <RouterView name="...">)
*
* @internal
*/
export interface _RouteFileInfoMap {
'pages/index.vue': {
routes:
| '/'
views:
| never
}
'pages/discord/rules.vue': {
routes:
| '/discord/rules'
views:
| never
}
'pages/kotoba.vue': {
routes:
| '/kotoba'
views:
| never
}
'pages/resources.vue': {
routes:
| '/resources'
views:
| never
}
}
/**
* Get a union of possible route names in a certain route component file.
* Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
*
* @internal
*/
export type _RouteNamesForFilePath<FilePath extends string> =
_RouteFileInfoMap extends Record<FilePath, infer Info>
? Info['routes']
: keyof RouteNamedMap
}

View file

@ -1,36 +1,23 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"noUncheckedIndexedAccess": true,
"module": "esnext",
"moduleResolution": "bundler",
"target": "esnext",
"lib": [
"ESNext",
"DOM",
],
"rootDir": "src",
"paths": {
"@/*": [
"./src/*"
]
},
},
"vueCompilerOptions": {
"strictTemplates": true,
},
"include": [
"src",
],
"exclude": [
"./eslint.config.js"
]
"extends": "@vue/tsconfig/tsconfig.dom.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
/* Linting */
"strict": true,
// "noUnusedLocals": true,
// "noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"noUncheckedIndexedAccess": true,
"module": "esnext",
"moduleResolution": "bundler",
"target": "esnext",
"lib": ["ESNext", "DOM"],
"rootDir": "src",
"paths": { "@/*": ["./src/*"] },
},
"vueCompilerOptions": { "strictTemplates": true },
"include": ["src"],
"exclude": ["./eslint.config.js"],
}