Compare commits
1 commit
main
...
exp-shephe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ded4e8439 |
22 changed files with 1496 additions and 91 deletions
125
library/i18n/locales/ar/neighbor.json
Normal file
125
library/i18n/locales/ar/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "جيراني من الشعوب غير المُبشَّرة",
|
||||
"chooseView": "اختر عرضًا",
|
||||
"views": {
|
||||
"cockpit": "نظرة عامة",
|
||||
"sendMap": "خريطة الإرسال",
|
||||
"flowerMesh": "زهرة الشبكة",
|
||||
"langCluster": "عناقيد اللغات",
|
||||
"flowers": "الزهور"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "مركز التصفية المتقاطعة",
|
||||
"sendMap": "أقواس من المُبشَّر إلى غير المُبشَّر",
|
||||
"flowerMesh": "تفتّح شعاعي",
|
||||
"langCluster": "مجموعات لغوية محددة",
|
||||
"flowers": "عائلة · لغة · لهجة، مع بتلات تفصيلية"
|
||||
},
|
||||
"title": {
|
||||
"overview": "جيراني · نظرة عامة",
|
||||
"send": "جيراني · SEND",
|
||||
"langClusters": "جيراني · عناقيد اللغات",
|
||||
"flowerMesh": "جيراني · زهرة الشبكة"
|
||||
},
|
||||
"search": "بحث",
|
||||
"searchCockpit": "ابحث عن هدف / مُرسِل / لغة…",
|
||||
"searchStrip": "ابحث عن هدف / لغة / مُرسِل…",
|
||||
"searchBrush": "بحث وتحديد",
|
||||
"remove": "إزالة {label}",
|
||||
"selectTarget": "اختر دولة الهدف غير المُبشَّر",
|
||||
"loadingSend": "جارٍ تحميل خريطة SEND…",
|
||||
"send": {
|
||||
"unreachedTarget": "هدف غير مُبشَّر —",
|
||||
"clickOne": "انقر واحدًا",
|
||||
"toFocus": "للتركيز عليه",
|
||||
"reachedSender": "مُرسِل مُبشَّر (SEND →)"
|
||||
},
|
||||
"pctChristian": "مسيحيون: {n}%",
|
||||
"groups": "الشعوب: {n}",
|
||||
"people": "السكان",
|
||||
"unreached": "غير مُبشَّر",
|
||||
"reached": "مُبشَّر",
|
||||
"unknown": "غير معروف",
|
||||
"lc": {
|
||||
"loading": "جارٍ تحميل الشعوب…",
|
||||
"apiDown": "واجهة doxa المباشرة غير متاحة: {message}",
|
||||
"clusters": "عناقيد لغوية",
|
||||
"pgs": "غير مُبشَّرة",
|
||||
"provinces": "مقاطعات IN/CN",
|
||||
"withReach": "لها مطابقة مُبشَّرة",
|
||||
"legendCluster": "عنقود لغوي غير مُبشَّر (الحجم = عدد الشعوب)",
|
||||
"legendReached": "جار مُبشَّر (مطابق باللغة)",
|
||||
"legendHelp": "حلقة خضراء = للعنقود مطابقة مُبشَّرة · انقر عنقودًا للتعمّق",
|
||||
"setCount": "Bounded set — شعوب غير مُبشَّرة: {n}",
|
||||
"more": "+{n} أخرى",
|
||||
"reachedSame": "جيران مُبشَّرون (اللغة نفسها): {n}",
|
||||
"frontier": "لا يشترك أي شعب مُبشَّر في هذه اللغة ضمن هذه البيانات. إنها جبهة جديدة: صلِّ من أجل الفعلة (لوقا 10:2).",
|
||||
"openFlower": "فتح عرض الزهرة ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "شبكة اللغة",
|
||||
"reachedNeighbors": "جيران مُبشَّرون",
|
||||
"countries": "دول",
|
||||
"upgsInCenter": "UPG في المركز",
|
||||
"meshLinks": "روابط الشبكة",
|
||||
"growing": "تنمو الزهرة…",
|
||||
"upgs": "UPG: {n}",
|
||||
"people": "السكان: {n}",
|
||||
"legendTitle": "الزهرة",
|
||||
"unreachedTarget": "هدف غير مُبشَّر (doxa-2000)",
|
||||
"reachedDeeper": "جار مُبشَّر (الأغمق = مسيحيون أكثر)",
|
||||
"sendPath": "مسار SEND ← إلى غير المُبشَّرين",
|
||||
"viaCluster": "عبر عنقود لغوي قريب",
|
||||
"mesh": "شبكة تعاون باللغة نفسها",
|
||||
"whorl": "الدائرة الداخلية = الدولة نفسها · البتلات = الدول المحيطة",
|
||||
"loadError": "تعذّر تحميل بيانات الجيران المُبشَّرين"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "العدسة",
|
||||
"lensAria": "عدسة اللغة",
|
||||
"noLens": "— بلا عدسة —",
|
||||
"color": "اللون",
|
||||
"colorAria": "لوّن المُرسِلين المُبشَّرين حسب",
|
||||
"pctReached": "% مُبشَّر",
|
||||
"religion": "الدين",
|
||||
"senderLanguage": "لغة المُرسِل",
|
||||
"senderCountry": "دولة المُرسِل",
|
||||
"clear": "مسح",
|
||||
"noSenders": "لا مُرسِلين",
|
||||
"byLanguage": "المُرسِلون حسب اللغة",
|
||||
"byCountry": "المُرسِلون حسب الدولة",
|
||||
"quantile": "% مُبشَّر (الشرائح)",
|
||||
"histogram": "مدرّج نسبة المُبشَّرين",
|
||||
"religionFamily": "عائلة الدين",
|
||||
"bridgeType": "نوع الجسر",
|
||||
"donut": "حلقة حسب الفئة"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· مخفيّة بالمرشحات: {n}",
|
||||
"clear": "مسح",
|
||||
"copy": "نسخ",
|
||||
"csvDownloaded": "تم تنزيل CSV ({n})",
|
||||
"copied": "تم النسخ ({n})",
|
||||
"copyFailed": "فشل النسخ — اضغط Ctrl/Cmd-C"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "التجميع حسب",
|
||||
"flowers": "زهور",
|
||||
"unreached": "غير مُبشَّرة",
|
||||
"legendTitle": "عناقيد الزهور",
|
||||
"legendCore": "عنقود لغوي غير مُبشَّر (نواة، الحجم = عدد الشعوب)",
|
||||
"legendPetal": "جار مُبشَّر (تفصيلي، إحداثيات حقيقية)",
|
||||
"legendHelp": "انقر دائرة عليا لإعادة التجميع · انقر نواة لتتفتح بتلاتها",
|
||||
"clustering": "جارٍ تجميع الحصاد حسب اللغة…",
|
||||
"signLanguage": "لغة الإشارة"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "ترميز اللون الأخضر",
|
||||
"provinces": "مقاطعات IN/CN",
|
||||
"provincesTitle": "إظهار حدود المقاطعات في IN/CN",
|
||||
"resetFocus": "✕ إلغاء التركيز",
|
||||
"needsToken": "تحتاج الخريطة إلى رمز Mapbox (tk في profile-config)…",
|
||||
"rendering": "جارٍ رسم حقل الحصاد…"
|
||||
},
|
||||
"bloom": "تفتّح"
|
||||
}
|
||||
125
library/i18n/locales/de/neighbor.json
Normal file
125
library/i18n/locales/de/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "Meine UPG-Nachbarn",
|
||||
"chooseView": "Ansicht wählen",
|
||||
"views": {
|
||||
"cockpit": "Überblick",
|
||||
"sendMap": "Sendekarte",
|
||||
"flowerMesh": "Blütennetz",
|
||||
"langCluster": "Sprachcluster",
|
||||
"flowers": "Blüten"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "Crossfilter-Zentrale",
|
||||
"sendMap": "Bögen von erreicht zu unerreicht",
|
||||
"flowerMesh": "radiale Blüte",
|
||||
"langCluster": "sprachlich begrenzte Mengen",
|
||||
"flowers": "Familie · Sprache · Dialekt als Kerne, feine Blütenblätter"
|
||||
},
|
||||
"title": {
|
||||
"overview": "Meine UPG-Nachbarn · Überblick",
|
||||
"send": "Meine UPG-Nachbarn · SEND",
|
||||
"langClusters": "Meine UPG-Nachbarn · Sprachcluster",
|
||||
"flowerMesh": "Meine UPG-Nachbarn · Blütennetz"
|
||||
},
|
||||
"search": "Suchen",
|
||||
"searchCockpit": "Ziel / Sender / Sprache suchen…",
|
||||
"searchStrip": "Ziel / Sprache / Sender suchen…",
|
||||
"searchBrush": "Suchen und auswählen",
|
||||
"remove": "{label} entfernen",
|
||||
"selectTarget": "Unerreichtes Zielland wählen",
|
||||
"loadingSend": "SEND-Karte wird geladen…",
|
||||
"send": {
|
||||
"unreachedTarget": "Unerreichtes Ziel —",
|
||||
"clickOne": "eines anklicken",
|
||||
"toFocus": "zum Fokussieren",
|
||||
"reachedSender": "Erreichter Sender (SEND →)"
|
||||
},
|
||||
"pctChristian": "{n} % Christen",
|
||||
"groups": "Gruppen: {n}",
|
||||
"people": "Menschen",
|
||||
"unreached": "unerreicht",
|
||||
"reached": "erreicht",
|
||||
"unknown": "Unbekannt",
|
||||
"lc": {
|
||||
"loading": "Volksgruppen werden geladen…",
|
||||
"apiDown": "Die Live-API von doxa ist nicht erreichbar: {message}",
|
||||
"clusters": "Sprachcluster",
|
||||
"pgs": "unerreicht",
|
||||
"provinces": "IN/CN-Provinzen",
|
||||
"withReach": "mit erreichter Entsprechung",
|
||||
"legendCluster": "Unerreichter Sprachcluster (Größe = Anzahl Gruppen)",
|
||||
"legendReached": "Erreichter Nachbar (über die Sprache zugeordnet)",
|
||||
"legendHelp": "grüner Ring = Cluster hat eine erreichte Entsprechung · Cluster anklicken zum Vertiefen",
|
||||
"setCount": "Bounded set — unerreichte Gruppen: {n}",
|
||||
"more": "+{n} weitere",
|
||||
"reachedSame": "Erreichte Nachbarn (gleiche Sprache): {n}",
|
||||
"frontier": "Keine erreichte Volksgruppe teilt diese Sprache in diesem Datensatz. Eine Grenze: betet um Arbeiter (Lukas 10,2).",
|
||||
"openFlower": "Blütenansicht öffnen ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "Sprachnetz",
|
||||
"reachedNeighbors": "erreichte Nachbarn",
|
||||
"countries": "Länder",
|
||||
"upgsInCenter": "UPGs im Zentrum",
|
||||
"meshLinks": "Netzverbindungen",
|
||||
"growing": "Die Blüte wächst…",
|
||||
"upgs": "UPGs: {n}",
|
||||
"people": "Menschen: {n}",
|
||||
"legendTitle": "Die Blüte",
|
||||
"unreachedTarget": "Unerreichtes Ziel (doxa-2000)",
|
||||
"reachedDeeper": "Erreichter Nachbar (dunkler = mehr Christen)",
|
||||
"sendPath": "SEND-Pfad → zu den Unerreichten",
|
||||
"viaCluster": "über einen verwandten Sprachcluster",
|
||||
"mesh": "Zusammenarbeitsnetz gleicher Sprache",
|
||||
"whorl": "innerer Kreis = gleiches Land · Blütenblätter = Nachbarländer",
|
||||
"loadError": "Die Daten der erreichten Nachbarn konnten nicht geladen werden"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "Linse",
|
||||
"lensAria": "Sprachlinse",
|
||||
"noLens": "— keine Linse —",
|
||||
"color": "Farbe",
|
||||
"colorAria": "Erreichte Sender färben nach",
|
||||
"pctReached": "% erreicht",
|
||||
"religion": "Religion",
|
||||
"senderLanguage": "Sprache des Senders",
|
||||
"senderCountry": "Land des Senders",
|
||||
"clear": "löschen",
|
||||
"noSenders": "keine Sender",
|
||||
"byLanguage": "Sender nach Sprache",
|
||||
"byCountry": "Sender nach Land",
|
||||
"quantile": "% erreicht (Quantile)",
|
||||
"histogram": "Histogramm des Erreichtheitsanteils",
|
||||
"religionFamily": "Religionsfamilie",
|
||||
"bridgeType": "Brückentyp",
|
||||
"donut": "Ring nach Kategorie"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· durch Filter ausgeblendet: {n}",
|
||||
"clear": "Löschen",
|
||||
"copy": "Kopieren",
|
||||
"csvDownloaded": "CSV heruntergeladen ({n})",
|
||||
"copied": "Kopiert ({n})",
|
||||
"copyFailed": "Kopieren fehlgeschlagen – Strg/Cmd-C drücken"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "Gruppieren nach",
|
||||
"flowers": "Blüten",
|
||||
"unreached": "unerreicht",
|
||||
"legendTitle": "Blütencluster",
|
||||
"legendCore": "Unerreichter Sprachcluster (Kern, Größe = Anzahl Gruppen)",
|
||||
"legendPetal": "Erreichter Nachbar (fein, echte Koordinaten)",
|
||||
"legendHelp": "oberen Kreis anklicken zum Neugruppieren · Kern anklicken, um die Blütenblätter zu öffnen",
|
||||
"clustering": "Die Ernte wird nach Sprache gruppiert…",
|
||||
"signLanguage": "Gebärdensprache"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "Kodierung der Grünfarbe",
|
||||
"provinces": "IN/CN-Provinzen",
|
||||
"provincesTitle": "Provinzgrenzen von IN/CN einblenden",
|
||||
"resetFocus": "✕ Fokus zurücksetzen",
|
||||
"needsToken": "Die Karte braucht einen Mapbox-Token (tk in profile-config)…",
|
||||
"rendering": "Das Erntefeld wird gezeichnet…"
|
||||
},
|
||||
"bloom": "Blüte"
|
||||
}
|
||||
125
library/i18n/locales/en/neighbor.json
Normal file
125
library/i18n/locales/en/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "My UPG Neighbors",
|
||||
"chooseView": "Choose a view",
|
||||
"views": {
|
||||
"cockpit": "Overview",
|
||||
"sendMap": "Send Map",
|
||||
"flowerMesh": "Flower Mesh",
|
||||
"langCluster": "Language Clusters",
|
||||
"flowers": "Flowers"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "crossfilter hub",
|
||||
"sendMap": "reached → unreached arcs",
|
||||
"flowerMesh": "radial bloom",
|
||||
"langCluster": "language bounded sets",
|
||||
"flowers": "family · language · dialect cores + granular petals"
|
||||
},
|
||||
"title": {
|
||||
"overview": "My UPG Neighbor · Overview",
|
||||
"send": "My UPG Neighbor · SEND",
|
||||
"langClusters": "My UPG Neighbor · Language Clusters",
|
||||
"flowerMesh": "My UPG Neighbor · Flower-Mesh"
|
||||
},
|
||||
"search": "Search",
|
||||
"searchCockpit": "Search target / sender / language…",
|
||||
"searchStrip": "Search target / language / sender…",
|
||||
"searchBrush": "Search and brush",
|
||||
"remove": "remove {label}",
|
||||
"selectTarget": "Select unreached target country",
|
||||
"loadingSend": "Loading SEND map…",
|
||||
"send": {
|
||||
"unreachedTarget": "Unreached target —",
|
||||
"clickOne": "click one",
|
||||
"toFocus": "to focus it",
|
||||
"reachedSender": "Reached sender (SEND →)"
|
||||
},
|
||||
"pctChristian": "{n}% Christian",
|
||||
"groups": "{n} groups",
|
||||
"people": "people",
|
||||
"unreached": "unreached",
|
||||
"reached": "reached",
|
||||
"unknown": "Unknown",
|
||||
"lc": {
|
||||
"loading": "Loading people groups…",
|
||||
"apiDown": "The live doxa API is unreachable: {message}",
|
||||
"clusters": "language clusters",
|
||||
"pgs": "unreached",
|
||||
"provinces": "IN/CN provinces",
|
||||
"withReach": "with a reached match",
|
||||
"legendCluster": "Unreached language cluster (size = number of groups)",
|
||||
"legendReached": "Reached neighbor (matched by language)",
|
||||
"legendHelp": "green ring = the cluster has a reached match · click a cluster to drill in",
|
||||
"setCount": "Bounded set — unreached groups: {n}",
|
||||
"more": "+{n} more",
|
||||
"reachedSame": "Reached neighbors (same language): {n}",
|
||||
"frontier": "No reached people group shares this language in this data set. A frontier: pray for laborers (Luke 10:2).",
|
||||
"openFlower": "Open flower view ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "language mesh",
|
||||
"reachedNeighbors": "reached neighbors",
|
||||
"countries": "countries",
|
||||
"upgsInCenter": "UPGs in the center",
|
||||
"meshLinks": "mesh links",
|
||||
"growing": "Growing the flower…",
|
||||
"upgs": "{n} UPGs",
|
||||
"people": "{n} people",
|
||||
"legendTitle": "The flower",
|
||||
"unreachedTarget": "Unreached target (doxa-2000)",
|
||||
"reachedDeeper": "Reached neighbor (deeper = more Christian)",
|
||||
"sendPath": "SEND path → into the unreached",
|
||||
"viaCluster": "via a related language cluster",
|
||||
"mesh": "Same-language collaboration mesh",
|
||||
"whorl": "inner whorl = same country · petals = surrounding countries",
|
||||
"loadError": "Could not load the reached-neighbor data"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "Lens",
|
||||
"lensAria": "Language lens",
|
||||
"noLens": "— no lens —",
|
||||
"color": "Color",
|
||||
"colorAria": "Color reached senders by",
|
||||
"pctReached": "% reached",
|
||||
"religion": "religion",
|
||||
"senderLanguage": "Sender language",
|
||||
"senderCountry": "Sender country",
|
||||
"clear": "clear",
|
||||
"noSenders": "no senders",
|
||||
"byLanguage": "Senders by language",
|
||||
"byCountry": "Senders by country",
|
||||
"quantile": "% reached (quantile)",
|
||||
"histogram": "Reached percent histogram",
|
||||
"religionFamily": "Religion family",
|
||||
"bridgeType": "Bridge type",
|
||||
"donut": "Donut by category"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· {n} hidden by filters",
|
||||
"clear": "Clear",
|
||||
"copy": "Copy",
|
||||
"csvDownloaded": "CSV downloaded ({n})",
|
||||
"copied": "Copied ({n})",
|
||||
"copyFailed": "Copy failed — press Ctrl/Cmd-C"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "Cluster by",
|
||||
"flowers": "flowers",
|
||||
"unreached": "unreached",
|
||||
"legendTitle": "Flower clusters",
|
||||
"legendCore": "Unreached language cluster (core, size = number of groups)",
|
||||
"legendPetal": "Reached neighbor (granular, real coordinates)",
|
||||
"legendHelp": "click a top circle to re-cluster · click a core to bloom its petals",
|
||||
"clustering": "Clustering the harvest by language…",
|
||||
"signLanguage": "Sign Language"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "Green color encoding",
|
||||
"provinces": "IN/CN provinces",
|
||||
"provincesTitle": "Overlay IN/CN admin-1 boundaries",
|
||||
"resetFocus": "✕ reset focus",
|
||||
"needsToken": "The map needs a Mapbox token (tk in profile-config)…",
|
||||
"rendering": "Rendering the harvest field…"
|
||||
},
|
||||
"bloom": "Bloom"
|
||||
}
|
||||
125
library/i18n/locales/es/neighbor.json
Normal file
125
library/i18n/locales/es/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "Mis vecinos UPG",
|
||||
"chooseView": "Elige una vista",
|
||||
"views": {
|
||||
"cockpit": "Resumen",
|
||||
"sendMap": "Mapa de envío",
|
||||
"flowerMesh": "Malla floral",
|
||||
"langCluster": "Grupos lingüísticos",
|
||||
"flowers": "Flores"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "centro de filtros cruzados",
|
||||
"sendMap": "arcos de alcanzado a no alcanzado",
|
||||
"flowerMesh": "floración radial",
|
||||
"langCluster": "conjuntos acotados por idioma",
|
||||
"flowers": "núcleos de familia · idioma · dialecto y pétalos detallados"
|
||||
},
|
||||
"title": {
|
||||
"overview": "Mis vecinos UPG · Resumen",
|
||||
"send": "Mis vecinos UPG · SEND",
|
||||
"langClusters": "Mis vecinos UPG · Grupos lingüísticos",
|
||||
"flowerMesh": "Mis vecinos UPG · Malla floral"
|
||||
},
|
||||
"search": "Buscar",
|
||||
"searchCockpit": "Buscar destino / emisor / idioma…",
|
||||
"searchStrip": "Buscar destino / idioma / emisor…",
|
||||
"searchBrush": "Buscar y seleccionar",
|
||||
"remove": "quitar {label}",
|
||||
"selectTarget": "Elige el país destino no alcanzado",
|
||||
"loadingSend": "Cargando mapa SEND…",
|
||||
"send": {
|
||||
"unreachedTarget": "Destino no alcanzado —",
|
||||
"clickOne": "haz clic en uno",
|
||||
"toFocus": "para enfocarlo",
|
||||
"reachedSender": "Emisor alcanzado (SEND →)"
|
||||
},
|
||||
"pctChristian": "{n} % cristianos",
|
||||
"groups": "grupos: {n}",
|
||||
"people": "personas",
|
||||
"unreached": "no alcanzado",
|
||||
"reached": "alcanzado",
|
||||
"unknown": "Desconocido",
|
||||
"lc": {
|
||||
"loading": "Cargando pueblos…",
|
||||
"apiDown": "La API en vivo de doxa no responde: {message}",
|
||||
"clusters": "grupos lingüísticos",
|
||||
"pgs": "no alcanzados",
|
||||
"provinces": "provincias IN/CN",
|
||||
"withReach": "con coincidencia alcanzada",
|
||||
"legendCluster": "Grupo lingüístico no alcanzado (tamaño = número de pueblos)",
|
||||
"legendReached": "Vecino alcanzado (emparejado por idioma)",
|
||||
"legendHelp": "anillo verde = el grupo tiene una coincidencia alcanzada · haz clic en un grupo para profundizar",
|
||||
"setCount": "Bounded set — pueblos no alcanzados: {n}",
|
||||
"more": "+{n} más",
|
||||
"reachedSame": "Vecinos alcanzados (mismo idioma): {n}",
|
||||
"frontier": "Ningún pueblo alcanzado comparte este idioma en estos datos. Una frontera: oren por obreros (Lucas 10:2).",
|
||||
"openFlower": "Abrir vista de flor ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "malla de idiomas",
|
||||
"reachedNeighbors": "vecinos alcanzados",
|
||||
"countries": "países",
|
||||
"upgsInCenter": "UPG en el centro",
|
||||
"meshLinks": "enlaces de la malla",
|
||||
"growing": "Creciendo la flor…",
|
||||
"upgs": "UPG: {n}",
|
||||
"people": "personas: {n}",
|
||||
"legendTitle": "La flor",
|
||||
"unreachedTarget": "Destino no alcanzado (doxa-2000)",
|
||||
"reachedDeeper": "Vecino alcanzado (más intenso = más cristianos)",
|
||||
"sendPath": "Ruta SEND → hacia los no alcanzados",
|
||||
"viaCluster": "por un grupo lingüístico afín",
|
||||
"mesh": "Malla de colaboración del mismo idioma",
|
||||
"whorl": "círculo interior = mismo país · pétalos = países vecinos",
|
||||
"loadError": "No se pudieron cargar los datos de vecinos alcanzados"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "Lente",
|
||||
"lensAria": "Lente de idioma",
|
||||
"noLens": "— sin lente —",
|
||||
"color": "Color",
|
||||
"colorAria": "Colorear emisores alcanzados por",
|
||||
"pctReached": "% alcanzado",
|
||||
"religion": "religión",
|
||||
"senderLanguage": "Idioma del emisor",
|
||||
"senderCountry": "País del emisor",
|
||||
"clear": "borrar",
|
||||
"noSenders": "sin emisores",
|
||||
"byLanguage": "Emisores por idioma",
|
||||
"byCountry": "Emisores por país",
|
||||
"quantile": "% alcanzado (cuantiles)",
|
||||
"histogram": "Histograma del porcentaje alcanzado",
|
||||
"religionFamily": "Familia religiosa",
|
||||
"bridgeType": "Tipo de puente",
|
||||
"donut": "Anillo por categoría"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· ocultos por filtros: {n}",
|
||||
"clear": "Borrar",
|
||||
"copy": "Copiar",
|
||||
"csvDownloaded": "CSV descargado ({n})",
|
||||
"copied": "Copiado ({n})",
|
||||
"copyFailed": "No se pudo copiar: pulsa Ctrl/Cmd-C"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "Agrupar por",
|
||||
"flowers": "flores",
|
||||
"unreached": "no alcanzados",
|
||||
"legendTitle": "Grupos florales",
|
||||
"legendCore": "Grupo lingüístico no alcanzado (núcleo, tamaño = número de pueblos)",
|
||||
"legendPetal": "Vecino alcanzado (detallado, coordenadas reales)",
|
||||
"legendHelp": "haz clic en un círculo superior para reagrupar · haz clic en un núcleo para abrir sus pétalos",
|
||||
"clustering": "Agrupando la cosecha por idioma…",
|
||||
"signLanguage": "Lengua de señas"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "Codificación del color verde",
|
||||
"provinces": "provincias IN/CN",
|
||||
"provincesTitle": "Mostrar límites provinciales de IN/CN",
|
||||
"resetFocus": "✕ quitar enfoque",
|
||||
"needsToken": "El mapa necesita un token de Mapbox (tk en profile-config)…",
|
||||
"rendering": "Dibujando el campo de cosecha…"
|
||||
},
|
||||
"bloom": "Floración"
|
||||
}
|
||||
125
library/i18n/locales/fr/neighbor.json
Normal file
125
library/i18n/locales/fr/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "Mes voisins UPG",
|
||||
"chooseView": "Choisir une vue",
|
||||
"views": {
|
||||
"cockpit": "Vue d’ensemble",
|
||||
"sendMap": "Carte d’envoi",
|
||||
"flowerMesh": "Maillage floral",
|
||||
"langCluster": "Groupes linguistiques",
|
||||
"flowers": "Fleurs"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "centre de filtrage croisé",
|
||||
"sendMap": "arcs des atteints vers les non-atteints",
|
||||
"flowerMesh": "floraison radiale",
|
||||
"langCluster": "ensembles bornés par langue",
|
||||
"flowers": "cœurs famille · langue · dialecte et pétales détaillés"
|
||||
},
|
||||
"title": {
|
||||
"overview": "Mes voisins UPG · Vue d’ensemble",
|
||||
"send": "Mes voisins UPG · SEND",
|
||||
"langClusters": "Mes voisins UPG · Groupes linguistiques",
|
||||
"flowerMesh": "Mes voisins UPG · Maillage floral"
|
||||
},
|
||||
"search": "Rechercher",
|
||||
"searchCockpit": "Rechercher une cible / un envoyeur / une langue…",
|
||||
"searchStrip": "Rechercher une cible / une langue / un envoyeur…",
|
||||
"searchBrush": "Rechercher et sélectionner",
|
||||
"remove": "retirer {label}",
|
||||
"selectTarget": "Choisir le pays cible non atteint",
|
||||
"loadingSend": "Chargement de la carte SEND…",
|
||||
"send": {
|
||||
"unreachedTarget": "Cible non atteinte —",
|
||||
"clickOne": "cliquez sur une",
|
||||
"toFocus": "pour la cibler",
|
||||
"reachedSender": "Envoyeur atteint (SEND →)"
|
||||
},
|
||||
"pctChristian": "{n} % de chrétiens",
|
||||
"groups": "groupes : {n}",
|
||||
"people": "personnes",
|
||||
"unreached": "non atteint",
|
||||
"reached": "atteint",
|
||||
"unknown": "Inconnu",
|
||||
"lc": {
|
||||
"loading": "Chargement des peuples…",
|
||||
"apiDown": "L’API doxa en direct est injoignable : {message}",
|
||||
"clusters": "groupes linguistiques",
|
||||
"pgs": "non atteints",
|
||||
"provinces": "provinces IN/CN",
|
||||
"withReach": "avec une correspondance atteinte",
|
||||
"legendCluster": "Groupe linguistique non atteint (taille = nombre de peuples)",
|
||||
"legendReached": "Voisin atteint (associé par la langue)",
|
||||
"legendHelp": "anneau vert = le groupe a une correspondance atteinte · cliquez sur un groupe pour l’explorer",
|
||||
"setCount": "Bounded set — peuples non atteints : {n}",
|
||||
"more": "+{n} de plus",
|
||||
"reachedSame": "Voisins atteints (même langue) : {n}",
|
||||
"frontier": "Aucun peuple atteint ne partage cette langue dans ces données. Une frontière : priez pour des ouvriers (Luc 10.2).",
|
||||
"openFlower": "Ouvrir la vue fleur ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "maillage linguistique",
|
||||
"reachedNeighbors": "voisins atteints",
|
||||
"countries": "pays",
|
||||
"upgsInCenter": "UPG au centre",
|
||||
"meshLinks": "liens du maillage",
|
||||
"growing": "La fleur pousse…",
|
||||
"upgs": "UPG : {n}",
|
||||
"people": "personnes : {n}",
|
||||
"legendTitle": "La fleur",
|
||||
"unreachedTarget": "Cible non atteinte (doxa-2000)",
|
||||
"reachedDeeper": "Voisin atteint (plus foncé = plus de chrétiens)",
|
||||
"sendPath": "Chemin SEND → vers les non-atteints",
|
||||
"viaCluster": "via un groupe linguistique apparenté",
|
||||
"mesh": "Maillage de collaboration de même langue",
|
||||
"whorl": "cercle intérieur = même pays · pétales = pays voisins",
|
||||
"loadError": "Impossible de charger les données des voisins atteints"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "Lentille",
|
||||
"lensAria": "Lentille linguistique",
|
||||
"noLens": "— aucune lentille —",
|
||||
"color": "Couleur",
|
||||
"colorAria": "Colorer les envoyeurs atteints par",
|
||||
"pctReached": "% atteint",
|
||||
"religion": "religion",
|
||||
"senderLanguage": "Langue de l’envoyeur",
|
||||
"senderCountry": "Pays de l’envoyeur",
|
||||
"clear": "effacer",
|
||||
"noSenders": "aucun envoyeur",
|
||||
"byLanguage": "Envoyeurs par langue",
|
||||
"byCountry": "Envoyeurs par pays",
|
||||
"quantile": "% atteint (quantiles)",
|
||||
"histogram": "Histogramme du pourcentage atteint",
|
||||
"religionFamily": "Famille religieuse",
|
||||
"bridgeType": "Type de pont",
|
||||
"donut": "Anneau par catégorie"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· masqués par les filtres : {n}",
|
||||
"clear": "Effacer",
|
||||
"copy": "Copier",
|
||||
"csvDownloaded": "CSV téléchargé ({n})",
|
||||
"copied": "Copié ({n})",
|
||||
"copyFailed": "Échec de la copie : appuyez sur Ctrl/Cmd-C"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "Regrouper par",
|
||||
"flowers": "fleurs",
|
||||
"unreached": "non atteints",
|
||||
"legendTitle": "Groupes floraux",
|
||||
"legendCore": "Groupe linguistique non atteint (cœur, taille = nombre de peuples)",
|
||||
"legendPetal": "Voisin atteint (détaillé, coordonnées réelles)",
|
||||
"legendHelp": "cliquez sur un cercle du haut pour regrouper · cliquez sur un cœur pour ouvrir ses pétales",
|
||||
"clustering": "Regroupement de la moisson par langue…",
|
||||
"signLanguage": "Langue des signes"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "Codage de la couleur verte",
|
||||
"provinces": "provinces IN/CN",
|
||||
"provincesTitle": "Afficher les limites des provinces IN/CN",
|
||||
"resetFocus": "✕ annuler le ciblage",
|
||||
"needsToken": "La carte a besoin d’un jeton Mapbox (tk dans profile-config)…",
|
||||
"rendering": "Dessin du champ de la moisson…"
|
||||
},
|
||||
"bloom": "Floraison"
|
||||
}
|
||||
125
library/i18n/locales/hi/neighbor.json
Normal file
125
library/i18n/locales/hi/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "मेरे UPG पड़ोसी",
|
||||
"chooseView": "दृश्य चुनें",
|
||||
"views": {
|
||||
"cockpit": "सारांश",
|
||||
"sendMap": "भेजने का नक्शा",
|
||||
"flowerMesh": "फूल-जाल",
|
||||
"langCluster": "भाषा समूह",
|
||||
"flowers": "फूल"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "क्रॉस-फ़िल्टर केंद्र",
|
||||
"sendMap": "पहुँचे से अपहुँचे तक चाप",
|
||||
"flowerMesh": "वृत्ताकार खिलना",
|
||||
"langCluster": "भाषा से सीमित समुच्चय",
|
||||
"flowers": "परिवार · भाषा · बोली के केंद्र और बारीक पंखुड़ियाँ"
|
||||
},
|
||||
"title": {
|
||||
"overview": "मेरे UPG पड़ोसी · सारांश",
|
||||
"send": "मेरे UPG पड़ोसी · SEND",
|
||||
"langClusters": "मेरे UPG पड़ोसी · भाषा समूह",
|
||||
"flowerMesh": "मेरे UPG पड़ोसी · फूल-जाल"
|
||||
},
|
||||
"search": "खोजें",
|
||||
"searchCockpit": "लक्ष्य / भेजने वाला / भाषा खोजें…",
|
||||
"searchStrip": "लक्ष्य / भाषा / भेजने वाला खोजें…",
|
||||
"searchBrush": "खोजें और चुनें",
|
||||
"remove": "{label} हटाएँ",
|
||||
"selectTarget": "अपहुँचा लक्ष्य देश चुनें",
|
||||
"loadingSend": "SEND नक्शा लोड हो रहा है…",
|
||||
"send": {
|
||||
"unreachedTarget": "अपहुँचा लक्ष्य —",
|
||||
"clickOne": "किसी एक पर क्लिक करें",
|
||||
"toFocus": "उस पर ध्यान केंद्रित करने के लिए",
|
||||
"reachedSender": "पहुँचा भेजने वाला (SEND →)"
|
||||
},
|
||||
"pctChristian": "ईसाई: {n}%",
|
||||
"groups": "समूह: {n}",
|
||||
"people": "लोग",
|
||||
"unreached": "अपहुँचा",
|
||||
"reached": "पहुँचा",
|
||||
"unknown": "अज्ञात",
|
||||
"lc": {
|
||||
"loading": "जनसमूह लोड हो रहे हैं…",
|
||||
"apiDown": "doxa का लाइव API उपलब्ध नहीं: {message}",
|
||||
"clusters": "भाषा समूह",
|
||||
"pgs": "अपहुँचे",
|
||||
"provinces": "IN/CN प्रांत",
|
||||
"withReach": "पहुँचे मेल वाले",
|
||||
"legendCluster": "अपहुँचा भाषा समूह (आकार = समूहों की संख्या)",
|
||||
"legendReached": "पहुँचा पड़ोसी (भाषा से मिलाया गया)",
|
||||
"legendHelp": "हरा घेरा = समूह का पहुँचा मेल है · गहराई से देखने के लिए किसी समूह पर क्लिक करें",
|
||||
"setCount": "Bounded set — अपहुँचे समूह: {n}",
|
||||
"more": "+{n} और",
|
||||
"reachedSame": "पहुँचे पड़ोसी (एक ही भाषा): {n}",
|
||||
"frontier": "इस डेटा में कोई पहुँचा जनसमूह यह भाषा नहीं बोलता। यह एक सीमांत है: मज़दूरों के लिए प्रार्थना करें (लूका 10:2)।",
|
||||
"openFlower": "फूल दृश्य खोलें ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "भाषा-जाल",
|
||||
"reachedNeighbors": "पहुँचे पड़ोसी",
|
||||
"countries": "देश",
|
||||
"upgsInCenter": "केंद्र में UPG",
|
||||
"meshLinks": "जाल की कड़ियाँ",
|
||||
"growing": "फूल बढ़ रहा है…",
|
||||
"upgs": "UPG: {n}",
|
||||
"people": "लोग: {n}",
|
||||
"legendTitle": "फूल",
|
||||
"unreachedTarget": "अपहुँचा लक्ष्य (doxa-2000)",
|
||||
"reachedDeeper": "पहुँचा पड़ोसी (गहरा = अधिक ईसाई)",
|
||||
"sendPath": "SEND मार्ग → अपहुँचों की ओर",
|
||||
"viaCluster": "संबंधित भाषा समूह के द्वारा",
|
||||
"mesh": "एक ही भाषा का सहयोग-जाल",
|
||||
"whorl": "भीतरी घेरा = वही देश · पंखुड़ियाँ = आसपास के देश",
|
||||
"loadError": "पहुँचे पड़ोसियों का डेटा लोड नहीं हो सका"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "लेंस",
|
||||
"lensAria": "भाषा लेंस",
|
||||
"noLens": "— कोई लेंस नहीं —",
|
||||
"color": "रंग",
|
||||
"colorAria": "पहुँचे भेजने वालों को इस आधार पर रंगें",
|
||||
"pctReached": "% पहुँचा",
|
||||
"religion": "धर्म",
|
||||
"senderLanguage": "भेजने वाले की भाषा",
|
||||
"senderCountry": "भेजने वाले का देश",
|
||||
"clear": "साफ़ करें",
|
||||
"noSenders": "कोई भेजने वाला नहीं",
|
||||
"byLanguage": "भाषा के अनुसार भेजने वाले",
|
||||
"byCountry": "देश के अनुसार भेजने वाले",
|
||||
"quantile": "% पहुँचा (क्वांटाइल)",
|
||||
"histogram": "पहुँच प्रतिशत का हिस्टोग्राम",
|
||||
"religionFamily": "धर्म परिवार",
|
||||
"bridgeType": "पुल का प्रकार",
|
||||
"donut": "श्रेणी के अनुसार रिंग"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· फ़िल्टर से छिपे: {n}",
|
||||
"clear": "साफ़ करें",
|
||||
"copy": "कॉपी करें",
|
||||
"csvDownloaded": "CSV डाउनलोड हुई ({n})",
|
||||
"copied": "कॉपी हुआ ({n})",
|
||||
"copyFailed": "कॉपी नहीं हुआ: Ctrl/Cmd-C दबाएँ"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "समूह बनाएँ",
|
||||
"flowers": "फूल",
|
||||
"unreached": "अपहुँचे",
|
||||
"legendTitle": "फूल-समूह",
|
||||
"legendCore": "अपहुँचा भाषा समूह (केंद्र, आकार = समूहों की संख्या)",
|
||||
"legendPetal": "पहुँचा पड़ोसी (बारीक, असली निर्देशांक)",
|
||||
"legendHelp": "फिर से समूह बनाने के लिए ऊपर के घेरे पर क्लिक करें · पंखुड़ियाँ खोलने के लिए केंद्र पर क्लिक करें",
|
||||
"clustering": "फ़सल को भाषा के अनुसार समूहित किया जा रहा है…",
|
||||
"signLanguage": "सांकेतिक भाषा"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "हरे रंग की कोडिंग",
|
||||
"provinces": "IN/CN प्रांत",
|
||||
"provincesTitle": "IN/CN प्रांतों की सीमाएँ दिखाएँ",
|
||||
"resetFocus": "✕ ध्यान हटाएँ",
|
||||
"needsToken": "नक्शे को Mapbox टोकन चाहिए (profile-config में tk)…",
|
||||
"rendering": "फ़सल का खेत बनाया जा रहा है…"
|
||||
},
|
||||
"bloom": "खिलना"
|
||||
}
|
||||
125
library/i18n/locales/it/neighbor.json
Normal file
125
library/i18n/locales/it/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "I miei vicini UPG",
|
||||
"chooseView": "Scegli una vista",
|
||||
"views": {
|
||||
"cockpit": "Panoramica",
|
||||
"sendMap": "Mappa di invio",
|
||||
"flowerMesh": "Rete floreale",
|
||||
"langCluster": "Gruppi linguistici",
|
||||
"flowers": "Fiori"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "centro dei filtri incrociati",
|
||||
"sendMap": "archi da raggiunti a non raggiunti",
|
||||
"flowerMesh": "fioritura radiale",
|
||||
"langCluster": "insiemi delimitati per lingua",
|
||||
"flowers": "nuclei di famiglia · lingua · dialetto e petali dettagliati"
|
||||
},
|
||||
"title": {
|
||||
"overview": "I miei vicini UPG · Panoramica",
|
||||
"send": "I miei vicini UPG · SEND",
|
||||
"langClusters": "I miei vicini UPG · Gruppi linguistici",
|
||||
"flowerMesh": "I miei vicini UPG · Rete floreale"
|
||||
},
|
||||
"search": "Cerca",
|
||||
"searchCockpit": "Cerca obiettivo / mittente / lingua…",
|
||||
"searchStrip": "Cerca obiettivo / lingua / mittente…",
|
||||
"searchBrush": "Cerca e seleziona",
|
||||
"remove": "rimuovi {label}",
|
||||
"selectTarget": "Scegli il paese obiettivo non raggiunto",
|
||||
"loadingSend": "Caricamento della mappa SEND…",
|
||||
"send": {
|
||||
"unreachedTarget": "Obiettivo non raggiunto —",
|
||||
"clickOne": "cliccane uno",
|
||||
"toFocus": "per metterlo a fuoco",
|
||||
"reachedSender": "Mittente raggiunto (SEND →)"
|
||||
},
|
||||
"pctChristian": "{n}% cristiani",
|
||||
"groups": "gruppi: {n}",
|
||||
"people": "persone",
|
||||
"unreached": "non raggiunto",
|
||||
"reached": "raggiunto",
|
||||
"unknown": "Sconosciuto",
|
||||
"lc": {
|
||||
"loading": "Caricamento dei popoli…",
|
||||
"apiDown": "L’API doxa in tempo reale non risponde: {message}",
|
||||
"clusters": "gruppi linguistici",
|
||||
"pgs": "non raggiunti",
|
||||
"provinces": "province IN/CN",
|
||||
"withReach": "con corrispondenza raggiunta",
|
||||
"legendCluster": "Gruppo linguistico non raggiunto (dimensione = numero di popoli)",
|
||||
"legendReached": "Vicino raggiunto (abbinato per lingua)",
|
||||
"legendHelp": "anello verde = il gruppo ha una corrispondenza raggiunta · clicca un gruppo per approfondire",
|
||||
"setCount": "Bounded set — popoli non raggiunti: {n}",
|
||||
"more": "+{n} altri",
|
||||
"reachedSame": "Vicini raggiunti (stessa lingua): {n}",
|
||||
"frontier": "Nessun popolo raggiunto condivide questa lingua in questi dati. Una frontiera: pregate per gli operai (Luca 10:2).",
|
||||
"openFlower": "Apri la vista fiore ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "rete linguistica",
|
||||
"reachedNeighbors": "vicini raggiunti",
|
||||
"countries": "paesi",
|
||||
"upgsInCenter": "UPG al centro",
|
||||
"meshLinks": "collegamenti della rete",
|
||||
"growing": "Il fiore sta crescendo…",
|
||||
"upgs": "UPG: {n}",
|
||||
"people": "persone: {n}",
|
||||
"legendTitle": "Il fiore",
|
||||
"unreachedTarget": "Obiettivo non raggiunto (doxa-2000)",
|
||||
"reachedDeeper": "Vicino raggiunto (più scuro = più cristiani)",
|
||||
"sendPath": "Percorso SEND → verso i non raggiunti",
|
||||
"viaCluster": "tramite un gruppo linguistico affine",
|
||||
"mesh": "Rete di collaborazione nella stessa lingua",
|
||||
"whorl": "cerchio interno = stesso paese · petali = paesi circostanti",
|
||||
"loadError": "Impossibile caricare i dati dei vicini raggiunti"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "Lente",
|
||||
"lensAria": "Lente linguistica",
|
||||
"noLens": "— nessuna lente —",
|
||||
"color": "Colore",
|
||||
"colorAria": "Colora i mittenti raggiunti per",
|
||||
"pctReached": "% raggiunto",
|
||||
"religion": "religione",
|
||||
"senderLanguage": "Lingua del mittente",
|
||||
"senderCountry": "Paese del mittente",
|
||||
"clear": "azzera",
|
||||
"noSenders": "nessun mittente",
|
||||
"byLanguage": "Mittenti per lingua",
|
||||
"byCountry": "Mittenti per paese",
|
||||
"quantile": "% raggiunto (quantili)",
|
||||
"histogram": "Istogramma della percentuale raggiunta",
|
||||
"religionFamily": "Famiglia religiosa",
|
||||
"bridgeType": "Tipo di ponte",
|
||||
"donut": "Anello per categoria"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· nascosti dai filtri: {n}",
|
||||
"clear": "Azzera",
|
||||
"copy": "Copia",
|
||||
"csvDownloaded": "CSV scaricato ({n})",
|
||||
"copied": "Copiato ({n})",
|
||||
"copyFailed": "Copia non riuscita: premi Ctrl/Cmd-C"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "Raggruppa per",
|
||||
"flowers": "fiori",
|
||||
"unreached": "non raggiunti",
|
||||
"legendTitle": "Gruppi floreali",
|
||||
"legendCore": "Gruppo linguistico non raggiunto (nucleo, dimensione = numero di popoli)",
|
||||
"legendPetal": "Vicino raggiunto (dettagliato, coordinate reali)",
|
||||
"legendHelp": "clicca un cerchio in alto per raggruppare · clicca un nucleo per aprire i petali",
|
||||
"clustering": "Raggruppamento del raccolto per lingua…",
|
||||
"signLanguage": "Lingua dei segni"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "Codifica del colore verde",
|
||||
"provinces": "province IN/CN",
|
||||
"provincesTitle": "Mostra i confini provinciali di IN/CN",
|
||||
"resetFocus": "✕ togli il focus",
|
||||
"needsToken": "La mappa richiede un token Mapbox (tk in profile-config)…",
|
||||
"rendering": "Disegno del campo del raccolto…"
|
||||
},
|
||||
"bloom": "Fioritura"
|
||||
}
|
||||
125
library/i18n/locales/pt/neighbor.json
Normal file
125
library/i18n/locales/pt/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "Meus vizinhos UPG",
|
||||
"chooseView": "Escolha uma vista",
|
||||
"views": {
|
||||
"cockpit": "Visão geral",
|
||||
"sendMap": "Mapa de envio",
|
||||
"flowerMesh": "Malha floral",
|
||||
"langCluster": "Grupos linguísticos",
|
||||
"flowers": "Flores"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "centro de filtros cruzados",
|
||||
"sendMap": "arcos de alcançado para não alcançado",
|
||||
"flowerMesh": "floração radial",
|
||||
"langCluster": "conjuntos delimitados por idioma",
|
||||
"flowers": "núcleos de família · idioma · dialeto e pétalas detalhadas"
|
||||
},
|
||||
"title": {
|
||||
"overview": "Meus vizinhos UPG · Visão geral",
|
||||
"send": "Meus vizinhos UPG · SEND",
|
||||
"langClusters": "Meus vizinhos UPG · Grupos linguísticos",
|
||||
"flowerMesh": "Meus vizinhos UPG · Malha floral"
|
||||
},
|
||||
"search": "Pesquisar",
|
||||
"searchCockpit": "Pesquisar destino / emissor / idioma…",
|
||||
"searchStrip": "Pesquisar destino / idioma / emissor…",
|
||||
"searchBrush": "Pesquisar e selecionar",
|
||||
"remove": "remover {label}",
|
||||
"selectTarget": "Escolha o país destino não alcançado",
|
||||
"loadingSend": "A carregar mapa SEND…",
|
||||
"send": {
|
||||
"unreachedTarget": "Destino não alcançado —",
|
||||
"clickOne": "clique num",
|
||||
"toFocus": "para o focar",
|
||||
"reachedSender": "Emissor alcançado (SEND →)"
|
||||
},
|
||||
"pctChristian": "{n}% cristãos",
|
||||
"groups": "grupos: {n}",
|
||||
"people": "pessoas",
|
||||
"unreached": "não alcançado",
|
||||
"reached": "alcançado",
|
||||
"unknown": "Desconhecido",
|
||||
"lc": {
|
||||
"loading": "A carregar povos…",
|
||||
"apiDown": "A API em direto da doxa não responde: {message}",
|
||||
"clusters": "grupos linguísticos",
|
||||
"pgs": "não alcançados",
|
||||
"provinces": "províncias IN/CN",
|
||||
"withReach": "com correspondência alcançada",
|
||||
"legendCluster": "Grupo linguístico não alcançado (tamanho = número de povos)",
|
||||
"legendReached": "Vizinho alcançado (associado pelo idioma)",
|
||||
"legendHelp": "anel verde = o grupo tem uma correspondência alcançada · clique num grupo para aprofundar",
|
||||
"setCount": "Bounded set — povos não alcançados: {n}",
|
||||
"more": "+{n} mais",
|
||||
"reachedSame": "Vizinhos alcançados (mesmo idioma): {n}",
|
||||
"frontier": "Nenhum povo alcançado partilha este idioma nestes dados. Uma fronteira: orem por trabalhadores (Lucas 10:2).",
|
||||
"openFlower": "Abrir vista de flor ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "malha de idiomas",
|
||||
"reachedNeighbors": "vizinhos alcançados",
|
||||
"countries": "países",
|
||||
"upgsInCenter": "UPG no centro",
|
||||
"meshLinks": "ligações da malha",
|
||||
"growing": "A flor está a crescer…",
|
||||
"upgs": "UPG: {n}",
|
||||
"people": "pessoas: {n}",
|
||||
"legendTitle": "A flor",
|
||||
"unreachedTarget": "Destino não alcançado (doxa-2000)",
|
||||
"reachedDeeper": "Vizinho alcançado (mais escuro = mais cristãos)",
|
||||
"sendPath": "Caminho SEND → para os não alcançados",
|
||||
"viaCluster": "por um grupo linguístico relacionado",
|
||||
"mesh": "Malha de colaboração do mesmo idioma",
|
||||
"whorl": "círculo interior = mesmo país · pétalas = países vizinhos",
|
||||
"loadError": "Não foi possível carregar os dados dos vizinhos alcançados"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "Lente",
|
||||
"lensAria": "Lente de idioma",
|
||||
"noLens": "— sem lente —",
|
||||
"color": "Cor",
|
||||
"colorAria": "Colorir emissores alcançados por",
|
||||
"pctReached": "% alcançado",
|
||||
"religion": "religião",
|
||||
"senderLanguage": "Idioma do emissor",
|
||||
"senderCountry": "País do emissor",
|
||||
"clear": "limpar",
|
||||
"noSenders": "sem emissores",
|
||||
"byLanguage": "Emissores por idioma",
|
||||
"byCountry": "Emissores por país",
|
||||
"quantile": "% alcançado (quantis)",
|
||||
"histogram": "Histograma da percentagem alcançada",
|
||||
"religionFamily": "Família religiosa",
|
||||
"bridgeType": "Tipo de ponte",
|
||||
"donut": "Anel por categoria"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· ocultos pelos filtros: {n}",
|
||||
"clear": "Limpar",
|
||||
"copy": "Copiar",
|
||||
"csvDownloaded": "CSV transferido ({n})",
|
||||
"copied": "Copiado ({n})",
|
||||
"copyFailed": "Falha ao copiar: prima Ctrl/Cmd-C"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "Agrupar por",
|
||||
"flowers": "flores",
|
||||
"unreached": "não alcançados",
|
||||
"legendTitle": "Grupos florais",
|
||||
"legendCore": "Grupo linguístico não alcançado (núcleo, tamanho = número de povos)",
|
||||
"legendPetal": "Vizinho alcançado (detalhado, coordenadas reais)",
|
||||
"legendHelp": "clique num círculo superior para reagrupar · clique num núcleo para abrir as pétalas",
|
||||
"clustering": "A agrupar a colheita por idioma…",
|
||||
"signLanguage": "Língua de sinais"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "Codificação da cor verde",
|
||||
"provinces": "províncias IN/CN",
|
||||
"provincesTitle": "Mostrar limites provinciais de IN/CN",
|
||||
"resetFocus": "✕ tirar foco",
|
||||
"needsToken": "O mapa precisa de um token Mapbox (tk em profile-config)…",
|
||||
"rendering": "A desenhar o campo da colheita…"
|
||||
},
|
||||
"bloom": "Floração"
|
||||
}
|
||||
125
library/i18n/locales/ro/neighbor.json
Normal file
125
library/i18n/locales/ro/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "Vecinii mei UPG",
|
||||
"chooseView": "Alegeți o vedere",
|
||||
"views": {
|
||||
"cockpit": "Prezentare",
|
||||
"sendMap": "Harta de trimitere",
|
||||
"flowerMesh": "Rețea florală",
|
||||
"langCluster": "Grupuri lingvistice",
|
||||
"flowers": "Flori"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "centru de filtrare încrucișată",
|
||||
"sendMap": "arce de la atinși la neatinși",
|
||||
"flowerMesh": "înflorire radială",
|
||||
"langCluster": "mulțimi delimitate după limbă",
|
||||
"flowers": "nuclee familie · limbă · dialect și petale detaliate"
|
||||
},
|
||||
"title": {
|
||||
"overview": "Vecinii mei UPG · Prezentare",
|
||||
"send": "Vecinii mei UPG · SEND",
|
||||
"langClusters": "Vecinii mei UPG · Grupuri lingvistice",
|
||||
"flowerMesh": "Vecinii mei UPG · Rețea florală"
|
||||
},
|
||||
"search": "Căutare",
|
||||
"searchCockpit": "Căutați țintă / expeditor / limbă…",
|
||||
"searchStrip": "Căutați țintă / limbă / expeditor…",
|
||||
"searchBrush": "Căutare și selecție",
|
||||
"remove": "eliminați {label}",
|
||||
"selectTarget": "Alegeți țara țintă neatinsă",
|
||||
"loadingSend": "Se încarcă harta SEND…",
|
||||
"send": {
|
||||
"unreachedTarget": "Țintă neatinsă —",
|
||||
"clickOne": "dați clic pe una",
|
||||
"toFocus": "pentru a o evidenția",
|
||||
"reachedSender": "Expeditor atins (SEND →)"
|
||||
},
|
||||
"pctChristian": "{n}% creștini",
|
||||
"groups": "grupuri: {n}",
|
||||
"people": "oameni",
|
||||
"unreached": "neatins",
|
||||
"reached": "atins",
|
||||
"unknown": "Necunoscut",
|
||||
"lc": {
|
||||
"loading": "Se încarcă popoarele…",
|
||||
"apiDown": "API-ul doxa în timp real nu răspunde: {message}",
|
||||
"clusters": "grupuri lingvistice",
|
||||
"pgs": "neatinse",
|
||||
"provinces": "provincii IN/CN",
|
||||
"withReach": "cu corespondență atinsă",
|
||||
"legendCluster": "Grup lingvistic neatins (mărime = numărul de popoare)",
|
||||
"legendReached": "Vecin atins (potrivit după limbă)",
|
||||
"legendHelp": "inel verde = grupul are o corespondență atinsă · dați clic pe un grup pentru detalii",
|
||||
"setCount": "Bounded set — popoare neatinse: {n}",
|
||||
"more": "+{n} în plus",
|
||||
"reachedSame": "Vecini atinși (aceeași limbă): {n}",
|
||||
"frontier": "Niciun popor atins nu vorbește această limbă în aceste date. O frontieră: rugați-vă pentru lucrători (Luca 10:2).",
|
||||
"openFlower": "Deschideți vederea floare ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "rețea lingvistică",
|
||||
"reachedNeighbors": "vecini atinși",
|
||||
"countries": "țări",
|
||||
"upgsInCenter": "UPG în centru",
|
||||
"meshLinks": "legături ale rețelei",
|
||||
"growing": "Floarea crește…",
|
||||
"upgs": "UPG: {n}",
|
||||
"people": "oameni: {n}",
|
||||
"legendTitle": "Floarea",
|
||||
"unreachedTarget": "Țintă neatinsă (doxa-2000)",
|
||||
"reachedDeeper": "Vecin atins (mai închis = mai mulți creștini)",
|
||||
"sendPath": "Calea SEND → spre cei neatinși",
|
||||
"viaCluster": "printr-un grup lingvistic înrudit",
|
||||
"mesh": "Rețea de colaborare în aceeași limbă",
|
||||
"whorl": "cercul interior = aceeași țară · petalele = țările din jur",
|
||||
"loadError": "Datele vecinilor atinși nu au putut fi încărcate"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "Lentilă",
|
||||
"lensAria": "Lentilă lingvistică",
|
||||
"noLens": "— fără lentilă —",
|
||||
"color": "Culoare",
|
||||
"colorAria": "Colorați expeditorii atinși după",
|
||||
"pctReached": "% atins",
|
||||
"religion": "religie",
|
||||
"senderLanguage": "Limba expeditorului",
|
||||
"senderCountry": "Țara expeditorului",
|
||||
"clear": "ștergeți",
|
||||
"noSenders": "niciun expeditor",
|
||||
"byLanguage": "Expeditori după limbă",
|
||||
"byCountry": "Expeditori după țară",
|
||||
"quantile": "% atins (cuantile)",
|
||||
"histogram": "Histograma procentului atins",
|
||||
"religionFamily": "Familie religioasă",
|
||||
"bridgeType": "Tip de punte",
|
||||
"donut": "Inel pe categorii"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· ascunși de filtre: {n}",
|
||||
"clear": "Ștergeți",
|
||||
"copy": "Copiați",
|
||||
"csvDownloaded": "CSV descărcat ({n})",
|
||||
"copied": "Copiat ({n})",
|
||||
"copyFailed": "Copierea a eșuat: apăsați Ctrl/Cmd-C"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "Grupați după",
|
||||
"flowers": "flori",
|
||||
"unreached": "neatinse",
|
||||
"legendTitle": "Grupuri florale",
|
||||
"legendCore": "Grup lingvistic neatins (nucleu, mărime = numărul de popoare)",
|
||||
"legendPetal": "Vecin atins (detaliat, coordonate reale)",
|
||||
"legendHelp": "clic pe un cerc de sus pentru regrupare · clic pe un nucleu pentru a-i deschide petalele",
|
||||
"clustering": "Se grupează recolta după limbă…",
|
||||
"signLanguage": "Limbajul semnelor"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "Codificarea culorii verzi",
|
||||
"provinces": "provincii IN/CN",
|
||||
"provincesTitle": "Afișați granițele provinciilor IN/CN",
|
||||
"resetFocus": "✕ anulați evidențierea",
|
||||
"needsToken": "Harta are nevoie de un token Mapbox (tk în profile-config)…",
|
||||
"rendering": "Se desenează câmpul recoltei…"
|
||||
},
|
||||
"bloom": "Înflorire"
|
||||
}
|
||||
125
library/i18n/locales/ru/neighbor.json
Normal file
125
library/i18n/locales/ru/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "Мои соседи UPG",
|
||||
"chooseView": "Выберите вид",
|
||||
"views": {
|
||||
"cockpit": "Обзор",
|
||||
"sendMap": "Карта отправки",
|
||||
"flowerMesh": "Цветочная сеть",
|
||||
"langCluster": "Языковые кластеры",
|
||||
"flowers": "Цветы"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "центр перекрёстной фильтрации",
|
||||
"sendMap": "дуги от охваченных к неохваченным",
|
||||
"flowerMesh": "радиальное цветение",
|
||||
"langCluster": "ограниченные языковые множества",
|
||||
"flowers": "ядра семья · язык · диалект и детальные лепестки"
|
||||
},
|
||||
"title": {
|
||||
"overview": "Мои соседи UPG · Обзор",
|
||||
"send": "Мои соседи UPG · SEND",
|
||||
"langClusters": "Мои соседи UPG · Языковые кластеры",
|
||||
"flowerMesh": "Мои соседи UPG · Цветочная сеть"
|
||||
},
|
||||
"search": "Поиск",
|
||||
"searchCockpit": "Искать цель / отправителя / язык…",
|
||||
"searchStrip": "Искать цель / язык / отправителя…",
|
||||
"searchBrush": "Поиск и выбор",
|
||||
"remove": "убрать {label}",
|
||||
"selectTarget": "Выберите неохваченную страну-цель",
|
||||
"loadingSend": "Загрузка карты SEND…",
|
||||
"send": {
|
||||
"unreachedTarget": "Неохваченная цель —",
|
||||
"clickOne": "нажмите на одну",
|
||||
"toFocus": "чтобы выделить её",
|
||||
"reachedSender": "Охваченный отправитель (SEND →)"
|
||||
},
|
||||
"pctChristian": "христиан: {n}%",
|
||||
"groups": "групп: {n}",
|
||||
"people": "человек",
|
||||
"unreached": "неохвачен",
|
||||
"reached": "охвачен",
|
||||
"unknown": "Неизвестно",
|
||||
"lc": {
|
||||
"loading": "Загрузка народов…",
|
||||
"apiDown": "Живой API doxa недоступен: {message}",
|
||||
"clusters": "языковых кластеров",
|
||||
"pgs": "неохваченных",
|
||||
"provinces": "провинций IN/CN",
|
||||
"withReach": "с охваченным соответствием",
|
||||
"legendCluster": "Неохваченный языковой кластер (размер = число групп)",
|
||||
"legendReached": "Охваченный сосед (сопоставлен по языку)",
|
||||
"legendHelp": "зелёное кольцо = у кластера есть охваченное соответствие · нажмите на кластер, чтобы углубиться",
|
||||
"setCount": "Bounded set — неохваченных групп: {n}",
|
||||
"more": "ещё {n}",
|
||||
"reachedSame": "Охваченные соседи (тот же язык): {n}",
|
||||
"frontier": "Ни один охваченный народ не говорит на этом языке в этих данных. Это рубеж: молитесь о делателях (Лк 10:2).",
|
||||
"openFlower": "Открыть вид цветка ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "языковая сеть",
|
||||
"reachedNeighbors": "охваченных соседей",
|
||||
"countries": "стран",
|
||||
"upgsInCenter": "UPG в центре",
|
||||
"meshLinks": "связей сети",
|
||||
"growing": "Цветок растёт…",
|
||||
"upgs": "UPG: {n}",
|
||||
"people": "человек: {n}",
|
||||
"legendTitle": "Цветок",
|
||||
"unreachedTarget": "Неохваченная цель (doxa-2000)",
|
||||
"reachedDeeper": "Охваченный сосед (темнее = больше христиан)",
|
||||
"sendPath": "Путь SEND → к неохваченным",
|
||||
"viaCluster": "через родственный языковой кластер",
|
||||
"mesh": "Сеть сотрудничества на одном языке",
|
||||
"whorl": "внутренний круг = та же страна · лепестки = соседние страны",
|
||||
"loadError": "Не удалось загрузить данные об охваченных соседях"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "Линза",
|
||||
"lensAria": "Языковая линза",
|
||||
"noLens": "— без линзы —",
|
||||
"color": "Цвет",
|
||||
"colorAria": "Окрашивать охваченных отправителей по",
|
||||
"pctReached": "% охвата",
|
||||
"religion": "религия",
|
||||
"senderLanguage": "Язык отправителя",
|
||||
"senderCountry": "Страна отправителя",
|
||||
"clear": "сбросить",
|
||||
"noSenders": "нет отправителей",
|
||||
"byLanguage": "Отправители по языку",
|
||||
"byCountry": "Отправители по стране",
|
||||
"quantile": "% охвата (квантили)",
|
||||
"histogram": "Гистограмма доли охвата",
|
||||
"religionFamily": "Религиозная семья",
|
||||
"bridgeType": "Тип моста",
|
||||
"donut": "Кольцо по категориям"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· скрыто фильтрами: {n}",
|
||||
"clear": "Сбросить",
|
||||
"copy": "Копировать",
|
||||
"csvDownloaded": "CSV загружен ({n})",
|
||||
"copied": "Скопировано ({n})",
|
||||
"copyFailed": "Не удалось скопировать: нажмите Ctrl/Cmd-C"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "Группировать по",
|
||||
"flowers": "цветов",
|
||||
"unreached": "неохваченных",
|
||||
"legendTitle": "Цветочные кластеры",
|
||||
"legendCore": "Неохваченный языковой кластер (ядро, размер = число групп)",
|
||||
"legendPetal": "Охваченный сосед (детально, реальные координаты)",
|
||||
"legendHelp": "нажмите верхний круг, чтобы перегруппировать · нажмите ядро, чтобы раскрыть лепестки",
|
||||
"clustering": "Группировка жатвы по языку…",
|
||||
"signLanguage": "Жестовый язык"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "Кодирование зелёного цвета",
|
||||
"provinces": "провинции IN/CN",
|
||||
"provincesTitle": "Показать границы провинций IN/CN",
|
||||
"resetFocus": "✕ сбросить выделение",
|
||||
"needsToken": "Карте нужен токен Mapbox (tk в profile-config)…",
|
||||
"rendering": "Рисуется поле жатвы…"
|
||||
},
|
||||
"bloom": "Цветение"
|
||||
}
|
||||
125
library/i18n/locales/zh/neighbor.json
Normal file
125
library/i18n/locales/zh/neighbor.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"brand": "我的 UPG 邻居",
|
||||
"chooseView": "选择视图",
|
||||
"views": {
|
||||
"cockpit": "概览",
|
||||
"sendMap": "差派地图",
|
||||
"flowerMesh": "花网",
|
||||
"langCluster": "语言群",
|
||||
"flowers": "花朵"
|
||||
},
|
||||
"hints": {
|
||||
"cockpit": "交叉筛选中心",
|
||||
"sendMap": "从已得之民到未得之民的弧线",
|
||||
"flowerMesh": "放射状绽放",
|
||||
"langCluster": "按语言划定的集合",
|
||||
"flowers": "语系 · 语言 · 方言为核心,细分花瓣"
|
||||
},
|
||||
"title": {
|
||||
"overview": "我的 UPG 邻居 · 概览",
|
||||
"send": "我的 UPG 邻居 · SEND",
|
||||
"langClusters": "我的 UPG 邻居 · 语言群",
|
||||
"flowerMesh": "我的 UPG 邻居 · 花网"
|
||||
},
|
||||
"search": "搜索",
|
||||
"searchCockpit": "搜索目标 / 差派方 / 语言…",
|
||||
"searchStrip": "搜索目标 / 语言 / 差派方…",
|
||||
"searchBrush": "搜索并选择",
|
||||
"remove": "移除 {label}",
|
||||
"selectTarget": "选择未得之民目标国家",
|
||||
"loadingSend": "正在加载 SEND 地图…",
|
||||
"send": {
|
||||
"unreachedTarget": "未得之民目标 —",
|
||||
"clickOne": "点击其中一个",
|
||||
"toFocus": "进行聚焦",
|
||||
"reachedSender": "已得之民差派方(SEND →)"
|
||||
},
|
||||
"pctChristian": "基督徒 {n}%",
|
||||
"groups": "族群:{n}",
|
||||
"people": "人口",
|
||||
"unreached": "未得",
|
||||
"reached": "已得",
|
||||
"unknown": "未知",
|
||||
"lc": {
|
||||
"loading": "正在加载族群…",
|
||||
"apiDown": "doxa 实时接口无法访问:{message}",
|
||||
"clusters": "语言群",
|
||||
"pgs": "未得",
|
||||
"provinces": "IN/CN 省份",
|
||||
"withReach": "有已得匹配",
|
||||
"legendCluster": "未得语言群(大小 = 族群数)",
|
||||
"legendReached": "已得邻居(按语言匹配)",
|
||||
"legendHelp": "绿环 = 该语言群有已得匹配 · 点击语言群深入查看",
|
||||
"setCount": "Bounded set — 未得族群:{n}",
|
||||
"more": "另有 {n} 个",
|
||||
"reachedSame": "已得邻居(同一语言):{n}",
|
||||
"frontier": "在此数据中没有已得族群使用这种语言。这是前沿:请为工人祷告(路加福音 10:2)。",
|
||||
"openFlower": "打开花朵视图 ▸"
|
||||
},
|
||||
"fm": {
|
||||
"languageMesh": "语言网",
|
||||
"reachedNeighbors": "已得邻居",
|
||||
"countries": "国家",
|
||||
"upgsInCenter": "中心的 UPG",
|
||||
"meshLinks": "网络连线",
|
||||
"growing": "花朵正在生长…",
|
||||
"upgs": "UPG:{n}",
|
||||
"people": "人口:{n}",
|
||||
"legendTitle": "花朵",
|
||||
"unreachedTarget": "未得之民目标(doxa-2000)",
|
||||
"reachedDeeper": "已得邻居(越深 = 基督徒越多)",
|
||||
"sendPath": "SEND 路径 → 通往未得之民",
|
||||
"viaCluster": "经由相关语言群",
|
||||
"mesh": "同语言协作网",
|
||||
"whorl": "内圈 = 同一国家 · 花瓣 = 周边国家",
|
||||
"loadError": "无法加载已得邻居数据"
|
||||
},
|
||||
"strip": {
|
||||
"lens": "透镜",
|
||||
"lensAria": "语言透镜",
|
||||
"noLens": "— 无透镜 —",
|
||||
"color": "颜色",
|
||||
"colorAria": "已得差派方的着色依据",
|
||||
"pctReached": "已得比例 %",
|
||||
"religion": "宗教",
|
||||
"senderLanguage": "差派方语言",
|
||||
"senderCountry": "差派方国家",
|
||||
"clear": "清除",
|
||||
"noSenders": "没有差派方",
|
||||
"byLanguage": "按语言统计差派方",
|
||||
"byCountry": "按国家统计差派方",
|
||||
"quantile": "已得比例 %(分位数)",
|
||||
"histogram": "已得比例直方图",
|
||||
"religionFamily": "宗教类别",
|
||||
"bridgeType": "桥梁类型",
|
||||
"donut": "按类别的环形图"
|
||||
},
|
||||
"list": {
|
||||
"hidden": "· 被筛选隐藏:{n}",
|
||||
"clear": "清除",
|
||||
"copy": "复制",
|
||||
"csvDownloaded": "已下载 CSV({n})",
|
||||
"copied": "已复制({n})",
|
||||
"copyFailed": "复制失败:请按 Ctrl/Cmd-C"
|
||||
},
|
||||
"fc": {
|
||||
"clusterBy": "分组依据",
|
||||
"flowers": "花朵",
|
||||
"unreached": "未得",
|
||||
"legendTitle": "花朵集群",
|
||||
"legendCore": "未得语言群(核心,大小 = 族群数)",
|
||||
"legendPetal": "已得邻居(细分,真实坐标)",
|
||||
"legendHelp": "点击上方圆圈重新分组 · 点击核心展开花瓣",
|
||||
"clustering": "正在按语言整理庄稼…",
|
||||
"signLanguage": "手语"
|
||||
},
|
||||
"mc": {
|
||||
"greenEncoding": "绿色编码",
|
||||
"provinces": "IN/CN 省份",
|
||||
"provincesTitle": "显示 IN/CN 省级边界",
|
||||
"resetFocus": "✕ 取消聚焦",
|
||||
"needsToken": "地图需要 Mapbox 令牌(profile-config 中的 tk)…",
|
||||
"rendering": "正在绘制庄稼田…"
|
||||
},
|
||||
"bloom": "绽放"
|
||||
}
|
||||
|
|
@ -136,15 +136,15 @@ useShadowStyles(`
|
|||
<div ref="rootEl" class="cpt-root">
|
||||
<!-- HEADER: brand · removable chips · search · honest counter · provenance pill -->
|
||||
<div class="cpt-header">
|
||||
<span class="cpt-brand">My UPG Neighbor · Overview</span>
|
||||
<span class="cpt-brand">{{ $t('neighbor.title.overview') }}</span>
|
||||
<div class="cpt-chips">
|
||||
<button v-for="(c, i) in store.chips.value" :key="i" class="cpt-chip" :class="{ focus: c.kind === 'focus' }"
|
||||
@click="store.removeChip(c)" :title="'remove ' + c.label">
|
||||
@click="store.removeChip(c)" :title="$t('neighbor.remove', { label: c.label })">
|
||||
{{ c.label }} <span class="x">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<input class="cpt-search" type="search" :value="store.search.value" @input="onSearch"
|
||||
placeholder="Search target / sender / language…" aria-label="Search" />
|
||||
:placeholder="$t('neighbor.searchCockpit')" :aria-label="$t('neighbor.search')" />
|
||||
<span class="cpt-counter">
|
||||
<b>{{ store.counts.value.senders.toLocaleString() }}</b> senders →
|
||||
<b>{{ store.counts.value.clusters.toLocaleString() }}</b> clusters · {{ store.counts.value.hidden }} hidden
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ useShadowStyles(`
|
|||
<input class="cs-search" type="search" :value="store.search.value"
|
||||
@input="onSearchInput" @focus="showSuggest = true"
|
||||
@blur="showSuggest = false"
|
||||
placeholder="Search target / language / sender…" aria-label="Search and brush" />
|
||||
:placeholder="$t('neighbor.searchStrip')" :aria-label="$t('neighbor.searchBrush')" />
|
||||
<ul v-if="showSuggest && suggestions.length" class="cs-suggest" role="listbox">
|
||||
<li v-for="(s, i) in suggestions" :key="i" :class="'t-' + s.type" role="option"
|
||||
@mousedown.prevent="pickSuggestion(s)">
|
||||
|
|
@ -254,19 +254,19 @@ useShadowStyles(`
|
|||
</div>
|
||||
|
||||
<label class="cs-lens">
|
||||
<span>Lens</span>
|
||||
<select :value="store.languageLens.value || ''" @change="onLens" aria-label="Language lens">
|
||||
<option value="">— no lens —</option>
|
||||
<span>{{ $t('neighbor.strip.lens') }}</span>
|
||||
<select :value="store.languageLens.value || ''" @change="onLens" :aria-label="$t('neighbor.strip.lensAria')">
|
||||
<option value="">{{ $t('neighbor.strip.noLens') }}</option>
|
||||
<option v-for="l in langCounts.slice(0, 40)" :key="l.lang" :value="l.lang">
|
||||
{{ l.lang }} ({{ l.count }})
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<div class="cs-colorby" role="group" aria-label="Color reached senders by">
|
||||
<span>Color</span>
|
||||
<button :class="{ on: store.colorBy.value === 'pct' }" @click="store.setColorBy('pct')">% reached</button>
|
||||
<button :class="{ on: store.colorBy.value === 'religion' }" @click="store.setColorBy('religion')">religion</button>
|
||||
<div class="cs-colorby" role="group" :aria-label="$t('neighbor.strip.colorAria')">
|
||||
<span>{{ $t('neighbor.strip.color') }}</span>
|
||||
<button :class="{ on: store.colorBy.value === 'pct' }" @click="store.setColorBy('pct')">{{ $t('neighbor.strip.pctReached') }}</button>
|
||||
<button :class="{ on: store.colorBy.value === 'religion' }" @click="store.setColorBy('religion')">{{ $t('neighbor.strip.religion') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -275,12 +275,12 @@ useShadowStyles(`
|
|||
<!-- 1) sender language bar -->
|
||||
<section class="cs-card">
|
||||
<header>
|
||||
<h4>Sender language</h4>
|
||||
<h4>{{ $t('neighbor.strip.senderLanguage') }}</h4>
|
||||
<button v-if="store.facets.value.languages.size" class="cs-clr"
|
||||
@click="store.facets.value.languages.forEach(v => store.toggleFacet('languages', v))">clear</button>
|
||||
@click="store.facets.value.languages.forEach(v => store.toggleFacet('languages', v))">{{ $t('neighbor.strip.clear') }}</button>
|
||||
</header>
|
||||
<svg v-if="langRows.length" class="cs-svg" :viewBox="'0 0 ' + BAR_VB_W + ' ' + barVbH(cd.languageBar)"
|
||||
preserveAspectRatio="xMinYMin meet" role="img" aria-label="Senders by language">
|
||||
preserveAspectRatio="xMinYMin meet" role="img" :aria-label="$t('neighbor.strip.byLanguage')">
|
||||
<g v-for="r in langRows" :key="r.key" class="cs-barrow" :class="{ active: r.active, dim: r.dim }"
|
||||
@click="store.toggleFacet('languages', r.key)">
|
||||
<text class="cs-blabel" :x="BAR_X - 4" :y="r.ty" text-anchor="end">{{ trunc(r.label, 13) }}</text>
|
||||
|
|
@ -288,18 +288,18 @@ useShadowStyles(`
|
|||
<text class="cs-bval" :x="r.vx" :y="r.ty">{{ r.value }}</text>
|
||||
</g>
|
||||
</svg>
|
||||
<p v-else class="cs-empty">no senders</p>
|
||||
<p v-else class="cs-empty">{{ $t('neighbor.strip.noSenders') }}</p>
|
||||
</section>
|
||||
|
||||
<!-- 2) sender country bar -->
|
||||
<section class="cs-card">
|
||||
<header>
|
||||
<h4>Sender country</h4>
|
||||
<h4>{{ $t('neighbor.strip.senderCountry') }}</h4>
|
||||
<button v-if="store.facets.value.countries.size" class="cs-clr"
|
||||
@click="store.facets.value.countries.forEach(v => store.toggleFacet('countries', v))">clear</button>
|
||||
@click="store.facets.value.countries.forEach(v => store.toggleFacet('countries', v))">{{ $t('neighbor.strip.clear') }}</button>
|
||||
</header>
|
||||
<svg v-if="countryRows.length" class="cs-svg" :viewBox="'0 0 ' + BAR_VB_W + ' ' + barVbH(cd.countryBar)"
|
||||
preserveAspectRatio="xMinYMin meet" role="img" aria-label="Senders by country">
|
||||
preserveAspectRatio="xMinYMin meet" role="img" :aria-label="$t('neighbor.strip.byCountry')">
|
||||
<g v-for="r in countryRows" :key="r.key" class="cs-barrow cs-barrow--country" :class="{ active: r.active, dim: r.dim }"
|
||||
@click="store.toggleFacet('countries', r.key)">
|
||||
<text class="cs-blabel" :x="BAR_X - 4" :y="r.ty" text-anchor="end">{{ trunc(r.label, 13) }}</text>
|
||||
|
|
@ -307,17 +307,17 @@ useShadowStyles(`
|
|||
<text class="cs-bval" :x="r.vx" :y="r.ty">{{ r.value }}</text>
|
||||
</g>
|
||||
</svg>
|
||||
<p v-else class="cs-empty">no senders</p>
|
||||
<p v-else class="cs-empty">{{ $t('neighbor.strip.noSenders') }}</p>
|
||||
</section>
|
||||
|
||||
<!-- 3) reached% quantile histogram (5 GREEN bins → reached-floor brush) -->
|
||||
<section class="cs-card">
|
||||
<header>
|
||||
<h4>% reached (quantile)</h4>
|
||||
<button v-if="store.facets.value.reachedMin != null" class="cs-clr" @click="store.setReachedMin(null)">clear</button>
|
||||
<h4>{{ $t('neighbor.strip.quantile') }}</h4>
|
||||
<button v-if="store.facets.value.reachedMin != null" class="cs-clr" @click="store.setReachedMin(null)">{{ $t('neighbor.strip.clear') }}</button>
|
||||
</header>
|
||||
<svg class="cs-svg" :viewBox="'0 0 ' + HIST_VB_W + ' ' + HIST_VB_H"
|
||||
preserveAspectRatio="xMidYMid meet" role="img" aria-label="Reached percent histogram">
|
||||
preserveAspectRatio="xMidYMid meet" role="img" :aria-label="$t('neighbor.strip.histogram')">
|
||||
<line class="cs-axis" :x1="HIST_L" :y1="HIST_BOT" :x2="HIST_VB_W - 4" :y2="HIST_BOT" />
|
||||
<g v-for="b in histBars" :key="b.key" class="cs-histbar" :class="{ active: b.active, dim: b.dim }"
|
||||
@click="onBin(b)">
|
||||
|
|
@ -331,13 +331,13 @@ useShadowStyles(`
|
|||
<!-- 4) bridge / religion donut -->
|
||||
<section class="cs-card">
|
||||
<header>
|
||||
<h4>{{ store.colorBy.value === 'religion' ? 'Religion family' : 'Bridge type' }}</h4>
|
||||
<h4>{{ store.colorBy.value === 'religion' ? $t('neighbor.strip.religionFamily') : $t('neighbor.strip.bridgeType') }}</h4>
|
||||
<button v-if="store.facets.value[donutKind].size" class="cs-clr"
|
||||
@click="store.facets.value[donutKind].forEach(v => store.toggleFacet(donutKind, v))">clear</button>
|
||||
@click="store.facets.value[donutKind].forEach(v => store.toggleFacet(donutKind, v))">{{ $t('neighbor.strip.clear') }}</button>
|
||||
</header>
|
||||
<div class="cs-donutwrap">
|
||||
<svg v-if="donutTotal" class="cs-donut" viewBox="0 0 160 160"
|
||||
preserveAspectRatio="xMidYMid meet" role="img" aria-label="Donut by category">
|
||||
preserveAspectRatio="xMidYMid meet" role="img" :aria-label="$t('neighbor.strip.donut')">
|
||||
<path v-for="d in donutArcs" :key="d.key" class="cs-arc" :class="{ active: d.active, dim: d.dim }"
|
||||
:d="d.path" :fill="d.color" @click="store.toggleFacet(donutKind, d.key)" />
|
||||
<text class="cs-dctr" x="80" y="84" text-anchor="middle">{{ donutTotal }}</text>
|
||||
|
|
@ -349,7 +349,7 @@ useShadowStyles(`
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p v-if="!donutTotal" class="cs-empty">no senders</p>
|
||||
<p v-if="!donutTotal" class="cs-empty">{{ $t('neighbor.strip.noSenders') }}</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ useShadowStyles(
|
|||
<div class="cpt-flower" @mousemove="onMove">
|
||||
<!-- header -->
|
||||
<div class="cf-bar">
|
||||
<span class="cf-title">Bloom</span>
|
||||
<span class="cf-title">{{ $t('neighbor.bloom') }}</span>
|
||||
<span v-if="placed" class="cf-meta">
|
||||
<b>{{ placed.center.country }}</b> · {{ placed.center.count }} unreached ·
|
||||
<b>{{ placed.shown }}</b>/{{ placed.total }} senders
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import { useShadowStyles } from '@map/composables/useShadowStyles.js'
|
|||
import { useLanguageFamilyLegendData } from '@map/composables/legends/useLanguageFamilyLegendData.js'
|
||||
import langFamilyByLanguage from '@map/data/langFamilyByLanguage.json'
|
||||
import bakedReached from '../data/reached-neighbors.json'
|
||||
import { useNeighborT } from '../composables/useNeighborT.js'
|
||||
const nt = useNeighborT()
|
||||
|
||||
const C_RED = '#e11d48', C_RED_DK = '#9f1239', C_NAVY = '#002e6e', C_GOLD = '#f59e0b'
|
||||
function reachedColor(pct) {
|
||||
|
|
@ -45,7 +47,7 @@ const cfg = computed(() => profileConfig?.value || {})
|
|||
const fcRoot = ref(null)
|
||||
const mapContainer = ref(null)
|
||||
const appReady = ref(false)
|
||||
const statusMsg = ref('Clustering the harvest by language…')
|
||||
const statusMsg = ref(nt('neighbor.fc.clustering'))
|
||||
const mode = ref('language') // 'family' | 'language' | 'dialect'
|
||||
const selectedKey = ref(null)
|
||||
const doxaFeatures = ref([]) // normalized doxa unreached for the taxonomy composable
|
||||
|
|
@ -333,7 +335,7 @@ const MODES = [
|
|||
<div v-if="!appReady" class="fc-loading">{{ statusMsg }}</div>
|
||||
|
||||
<!-- the 3 cluster-by MODE CIRCLES -->
|
||||
<div class="fc-modes" role="tablist" aria-label="Cluster by">
|
||||
<div class="fc-modes" role="tablist" :aria-label="$t('neighbor.fc.clusterBy')">
|
||||
<button v-for="md in MODES" :key="md.key" class="fc-mode" :class="{ on: mode === md.key }"
|
||||
role="tab" :aria-selected="mode === md.key" @click="setMode(md.key)">
|
||||
<span class="fc-circle">{{ md.label.slice(0,3).toUpperCase() }}</span>
|
||||
|
|
@ -343,15 +345,15 @@ const MODES = [
|
|||
</div>
|
||||
|
||||
<div v-if="appReady" class="fc-stats">
|
||||
<b>{{ stats.cores }}</b> flowers · <b>{{ stats.unreached.toLocaleString() }}</b> unreached<br>
|
||||
{{ $t('neighbor.fc.flowers') }}: <b>{{ stats.cores }}</b> · {{ $t('neighbor.fc.unreached') }}: <b>{{ stats.unreached.toLocaleString() }}</b><br>
|
||||
<b>{{ stats.petals.toLocaleString() }}</b> reached petals · by {{ mode }}
|
||||
</div>
|
||||
|
||||
<div v-if="appReady" class="fc-legend">
|
||||
<h4>Flower clusters</h4>
|
||||
<div class="fc-lrow"><span class="fc-dot" :style="{ background: C_RED }"></span> Unreached language cluster (core, size = #PGs)</div>
|
||||
<div class="fc-lrow"><span class="fc-dot" :style="{ background: reachedColor(80) }"></span> Reached neighbor (granular, real coord)</div>
|
||||
<div class="fc-lrow" style="color:#6b7280;font-size:10px;margin-top:4px">click a top circle to re-cluster · click a core to bloom its petals</div>
|
||||
<h4>{{ $t('neighbor.fc.legendTitle') }}</h4>
|
||||
<div class="fc-lrow"><span class="fc-dot" :style="{ background: C_RED }"></span> {{ $t('neighbor.fc.legendCore') }}</div>
|
||||
<div class="fc-lrow"><span class="fc-dot" :style="{ background: reachedColor(80) }"></span> {{ $t('neighbor.fc.legendPetal') }}</div>
|
||||
<div class="fc-lrow" style="color:#6b7280;font-size:10px;margin-top:4px">{{ $t('neighbor.fc.legendHelp') }}</div>
|
||||
</div>
|
||||
|
||||
<div v-if="appReady" class="fc-footer">
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ import {
|
|||
useCockpitStore, COLORS, GREEN_BIN_LABELS,
|
||||
reachedColor, quantileBin, bridgeDash, fmtPop
|
||||
} from './useCockpit.js'
|
||||
import { useNeighborT } from '../composables/useNeighborT.js'
|
||||
const nt = useNeighborT()
|
||||
|
||||
const store = useCockpitStore()
|
||||
|
||||
|
|
@ -95,7 +97,7 @@ const exportRows = computed(() => selCount.value ? selectedRows.value : rows.val
|
|||
function exportCsv() {
|
||||
if (!exportRows.value.length) return
|
||||
store.exportSelectionCSV(exportRows.value)
|
||||
copyFlash.value = 'CSV downloaded (' + exportRows.value.length + ')'
|
||||
copyFlash.value = nt('neighbor.list.csvDownloaded', { n: exportRows.value.length })
|
||||
flashClear()
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +140,7 @@ async function copyList() {
|
|||
await navigator.clipboard.writeText(text); ok = true
|
||||
} else { ok = legacyCopy(text) }
|
||||
} catch (_) { ok = legacyCopy(text) }
|
||||
copyFlash.value = ok ? 'Copied (' + list.length + ')' : 'Copy failed — press Ctrl/Cmd-C'
|
||||
copyFlash.value = ok ? nt('neighbor.list.copied', { n: list.length }) : nt('neighbor.list.copyFailed')
|
||||
flashClear()
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +293,7 @@ useShadowStyles(`
|
|||
<span class="cpt-l-badge">
|
||||
<b>{{ availableTotal.toLocaleString() }}</b> senders available
|
||||
</span>
|
||||
<span v-if="hiddenCount" class="cpt-l-hidden">· {{ hiddenCount.toLocaleString() }} hidden by filters</span>
|
||||
<span v-if="hiddenCount" class="cpt-l-hidden">{{ $t('neighbor.list.hidden', { n: hiddenCount.toLocaleString() }) }}</span>
|
||||
</div>
|
||||
<div class="cpt-l-sorts" v-if="focusedTarget">
|
||||
<button
|
||||
|
|
@ -314,8 +316,8 @@ useShadowStyles(`
|
|||
</label>
|
||||
<span class="cpt-l-spacer"></span>
|
||||
<span class="cpt-l-flash" :class="{ warn: copyFlash.indexOf('fail') !== -1 }">{{ copyFlash }}</span>
|
||||
<button class="cpt-l-btn ghost" type="button" v-if="selCount" @click="clearSelection">Clear</button>
|
||||
<button class="cpt-l-btn" type="button" :disabled="!exportRows.length" @click="copyList">Copy</button>
|
||||
<button class="cpt-l-btn ghost" type="button" v-if="selCount" @click="clearSelection">{{ $t('neighbor.list.clear') }}</button>
|
||||
<button class="cpt-l-btn" type="button" :disabled="!exportRows.length" @click="copyList">{{ $t('neighbor.list.copy') }}</button>
|
||||
<button class="cpt-l-btn primary" type="button" :disabled="!exportRows.length" @click="exportCsv">
|
||||
Export {{ selCount ? 'selection' : 'all' }} · CSV
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -458,13 +458,13 @@ useShadowStyles(`
|
|||
|
||||
<!-- on-map controls: exposes color-by (8) + province drill (9) + reset focus -->
|
||||
<div v-if="ready" class="cpt-mc-ctl">
|
||||
<div class="cpt-mc-seg" role="group" aria-label="Green color encoding">
|
||||
<button :class="{ on: store.colorBy.value === 'pct' }" @click="store.setColorBy('pct')">% reached</button>
|
||||
<button :class="{ on: store.colorBy.value === 'religion' }" @click="store.setColorBy('religion')">religion</button>
|
||||
<div class="cpt-mc-seg" role="group" :aria-label="$t('neighbor.mc.greenEncoding')">
|
||||
<button :class="{ on: store.colorBy.value === 'pct' }" @click="store.setColorBy('pct')">{{ $t('neighbor.strip.pctReached') }}</button>
|
||||
<button :class="{ on: store.colorBy.value === 'religion' }" @click="store.setColorBy('religion')">{{ $t('neighbor.strip.religion') }}</button>
|
||||
</div>
|
||||
<button class="cpt-mc-btn" :class="{ on: store.provinceDrill.value }" @click="store.toggleProvince()"
|
||||
title="Overlay IN/CN admin-1 boundaries">IN/CN provinces</button>
|
||||
<button v-if="store.focusedTarget.value" class="cpt-mc-btn gold" @click="store.clearFocus()">✕ reset focus</button>
|
||||
:title="$t('neighbor.mc.provincesTitle')">{{ $t('neighbor.mc.provinces') }}</button>
|
||||
<button v-if="store.focusedTarget.value" class="cpt-mc-btn gold" @click="store.clearFocus()">{{ $t('neighbor.mc.resetFocus') }}</button>
|
||||
</div>
|
||||
|
||||
<!-- SEND headline when focused -->
|
||||
|
|
@ -472,8 +472,8 @@ useShadowStyles(`
|
|||
|
||||
<!-- token/load hint (map never initialized — store still drives the other cells) -->
|
||||
<div v-if="!ready" class="cpt-mc-loading">
|
||||
<span v-if="tokenMissing">Map needs a Mapbox token (tk in profile-config)…</span>
|
||||
<span v-else>Rendering the harvest field…</span>
|
||||
<span v-if="tokenMissing">{{ $t('neighbor.mc.needsToken') }}</span>
|
||||
<span v-else>{{ $t('neighbor.mc.rendering') }}</span>
|
||||
</div>
|
||||
|
||||
<!-- hover-pin tooltip -->
|
||||
|
|
|
|||
19
plugin-designs/upg-neighbor/src/composables/useNeighborT.js
Normal file
19
plugin-designs/upg-neighbor/src/composables/useNeighborT.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// useNeighborT — My UPG Neighbors' UI text: library/i18n/locales/<lc>/neighbor.json (11 locales).
|
||||
// Chrome only, by decision (dx-shepherd, 2026-09-26): research terms, provenance lines and proper
|
||||
// nouns (SEND, doxa-2000, Bounded set, JP, PPLR…) stay in English as named sources.
|
||||
// i18n is OPTIONAL: useI18n() throws on a host that never installed it, so the English catalog is
|
||||
// the fallback, never a blank or a raw key. Call it inside setup().
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import enNeighbor from '@map/i18n/locales/en/neighbor.json'
|
||||
|
||||
const enLookup = (key) => String(key).replace(/^neighbor\./, '').split('.').reduce((o, k) => (o == null ? o : o[k]), enNeighbor)
|
||||
const fill = (str, params) => (params ? String(str).replace(/\{(\w+)\}/g, (m, k) => (k in params ? params[k] : m)) : str)
|
||||
|
||||
export function useNeighborT() {
|
||||
try {
|
||||
const i18n = useI18n()
|
||||
return (key, params) => { const v = i18n.t(key, params || {}); return v === key ? fill(enLookup(key) ?? key, params) : v }
|
||||
} catch (_) {
|
||||
return (key, params) => fill(enLookup(key) ?? String(key), params)
|
||||
}
|
||||
}
|
||||
|
|
@ -261,9 +261,9 @@ function onNodeEnter(p, ev) {
|
|||
x: ev.clientX, y: ev.clientY,
|
||||
html: `<strong>${esc(n.name)}</strong>`
|
||||
+ `<div class="fm-tip-sub">${esc(n.country)}${prov ? ' · ' + esc(prov) : ''}</div>`
|
||||
+ `<div class="fm-tip-row"><span class="fm-tip-k">reached</span> ${Math.round(n.pct_christian || 0)}% Christian</div>`
|
||||
+ `<div class="fm-tip-row"><span class="fm-tip-k">${nt('neighbor.reached')}</span> ${nt('neighbor.pctChristian', { n: Math.round(n.pct_christian || 0) })}</div>`
|
||||
+ `<div class="fm-tip-row"><span class="fm-tip-k">language</span> ${esc(n.lang || '—')}</div>`
|
||||
+ `<div class="fm-tip-row"><span class="fm-tip-k">people</span> ${fmtPop(n.pop)}</div>`
|
||||
+ `<div class="fm-tip-row"><span class="fm-tip-k">${nt('neighbor.people')}</span> ${fmtPop(n.pop)}</div>`
|
||||
+ `<div class="fm-tip-row"><span class="fm-tip-k">bridge</span> ${esc(n.bridge || '—')}</div>`
|
||||
+ `<div class="fm-tip-row"><span class="fm-tip-k">near</span> ${esc(n.adjacency || '—')}</div>`
|
||||
}
|
||||
|
|
@ -286,6 +286,8 @@ function esc(s) {
|
|||
// platform gem-frame (it worked in `npm run dev` only — Vite serves the source data dir there). A
|
||||
// profile-config `dataUrl` still overrides live. Same harness-vs-platform class as the ProfileLoader fix.
|
||||
import bakedReached from './data/reached-neighbors.json'
|
||||
import { useNeighborT } from './composables/useNeighborT.js'
|
||||
const nt = useNeighborT()
|
||||
async function loadDataset() {
|
||||
const cfgUrl = cfg.value.dataUrl
|
||||
if (cfgUrl) {
|
||||
|
|
@ -314,7 +316,7 @@ async function enrichCenterLive() {
|
|||
onMounted(async () => {
|
||||
dataset.value = await loadDataset()
|
||||
if (!dataset.value) {
|
||||
loadError.value = 'Could not load reached-neighbors.json'
|
||||
loadError.value = nt('neighbor.fm.loadError')
|
||||
appReady.value = true
|
||||
return
|
||||
}
|
||||
|
|
@ -414,26 +416,26 @@ useShadowStyles(`
|
|||
<div class="fm-root" @mousemove="onMove">
|
||||
<!-- top bar -->
|
||||
<div class="fm-top">
|
||||
<span class="fm-title">My UPG Neighbor · Flower-Mesh</span>
|
||||
<span class="fm-title">{{ $t('neighbor.title.flowerMesh') }}</span>
|
||||
<select v-if="targetNames.length" class="fm-select"
|
||||
:value="activeTarget" @change="onSelectTarget"
|
||||
aria-label="Select unreached target country">
|
||||
:aria-label="$t('neighbor.selectTarget')">
|
||||
<option v-for="name in targetNames" :key="name" :value="name">{{ name }}</option>
|
||||
</select>
|
||||
<span class="fm-toggle" :class="{ on: showMesh }" role="switch" :aria-checked="showMesh"
|
||||
tabindex="0" @click="showMesh = !showMesh"
|
||||
@keydown.enter.prevent="showMesh = !showMesh" @keydown.space.prevent="showMesh = !showMesh">
|
||||
<span class="fm-sw"></span> language mesh
|
||||
<span class="fm-sw"></span> {{ $t('neighbor.fm.languageMesh') }}
|
||||
</span>
|
||||
<span v-if="targetRec" class="fm-stats">
|
||||
<b>{{ stats.total }}</b> reached neighbors · <b>{{ stats.countries }}</b> countries<br>
|
||||
<b>{{ fmt(center.upg) }}</b> UPGs in center · <b>{{ stats.meshes }}</b> mesh links
|
||||
{{ $t('neighbor.fm.reachedNeighbors') }}: <b>{{ stats.total }}</b> · {{ $t('neighbor.fm.countries') }}: <b>{{ stats.countries }}</b><br>
|
||||
{{ $t('neighbor.fm.upgsInCenter') }}: <b>{{ fmt(center.upg) }}</b> · {{ $t('neighbor.fm.meshLinks') }}: <b>{{ stats.meshes }}</b>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- the flower -->
|
||||
<div class="fm-stage">
|
||||
<div v-if="!appReady" class="fm-loading">Growing the flower…</div>
|
||||
<div v-if="!appReady" class="fm-loading">{{ $t('neighbor.fm.growing') }}</div>
|
||||
<div v-else-if="loadError" class="fm-loading">{{ loadError }}</div>
|
||||
|
||||
<svg v-else class="fm-svg" :viewBox="`0 0 ${VB} ${VB}`"
|
||||
|
|
@ -469,7 +471,7 @@ useShadowStyles(`
|
|||
:class="{ dim: !isNodeLit(p), sel: p.id === selectedId }"
|
||||
@click.stop="onNodeClick(p)"
|
||||
@mouseenter="onNodeEnter(p, $event)" @mouseleave="onNodeLeave">
|
||||
<title>{{ p.node.name }} — {{ Math.round(p.node.pct_christian || 0) }}% Christian, {{ p.node.lang }}</title>
|
||||
<title>{{ p.node.name }} — {{ $t('neighbor.pctChristian', { n: Math.round(p.node.pct_christian || 0) }) }}, {{ p.node.lang }}</title>
|
||||
<circle :cx="p.x" :cy="p.y" :r="p.r" :fill="p.color" />
|
||||
<text v-if="p.r >= 9 || p.id === selectedId" class="fm-node-label"
|
||||
:x="p.x" :y="p.y + p.r + 14">{{ p.node.name }}</text>
|
||||
|
|
@ -481,20 +483,20 @@ useShadowStyles(`
|
|||
<circle class="fm-center-glow" :cx="CX" :cy="CY" :r="R_CTR + 26" />
|
||||
<circle :cx="CX" :cy="CY" :r="R_CTR" />
|
||||
<text class="fm-center-name" :x="CX" :y="CY - 2">{{ center.name }}</text>
|
||||
<text class="fm-center-sub" :x="CX" :y="CY + 16">{{ fmt(center.upg) }} UPGs</text>
|
||||
<text class="fm-center-sub" :x="CX" :y="CY + 30" style="opacity:.85">{{ fmtPop(center.pop) }} people</text>
|
||||
<text class="fm-center-sub" :x="CX" :y="CY + 16">{{ $t('neighbor.fm.upgs', { n: fmt(center.upg) }) }}</text>
|
||||
<text class="fm-center-sub" :x="CX" :y="CY + 30" style="opacity:.85">{{ $t('neighbor.fm.people', { n: fmtPop(center.pop) }) }}</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<!-- legend -->
|
||||
<div v-if="appReady && !loadError" class="fm-legend">
|
||||
<h4>The flower</h4>
|
||||
<div class="fm-lrow"><span class="fm-dot" :style="{ background: C_ORANGE }"></span> Unreached target (doxa-2000)</div>
|
||||
<div class="fm-lrow"><span class="fm-dot" :style="{ background: reachedColor(90) }"></span> Reached neighbor (deeper = more Christian)</div>
|
||||
<div class="fm-lrow"><span class="fm-line" style="border-color:#5b7fd0"></span> SEND path → into the unreached</div>
|
||||
<div class="fm-lrow"><span class="fm-line" style="border-color:#3a4f86;border-top-style:dashed"></span> via related language cluster</div>
|
||||
<div class="fm-lrow"><span class="fm-line" style="border-color:#ffae66"></span> Same-language collaboration mesh</div>
|
||||
<div class="fm-lrow" style="color:#7e90b6;margin-top:5px;font-size:10px">inner whorl = same country · petals = surrounding countries</div>
|
||||
<h4>{{ $t('neighbor.fm.legendTitle') }}</h4>
|
||||
<div class="fm-lrow"><span class="fm-dot" :style="{ background: C_ORANGE }"></span> {{ $t('neighbor.fm.unreachedTarget') }}</div>
|
||||
<div class="fm-lrow"><span class="fm-dot" :style="{ background: reachedColor(90) }"></span> {{ $t('neighbor.fm.reachedDeeper') }}</div>
|
||||
<div class="fm-lrow"><span class="fm-line" style="border-color:#5b7fd0"></span> {{ $t('neighbor.fm.sendPath') }}</div>
|
||||
<div class="fm-lrow"><span class="fm-line" style="border-color:#3a4f86;border-top-style:dashed"></span> {{ $t('neighbor.fm.viaCluster') }}</div>
|
||||
<div class="fm-lrow"><span class="fm-line" style="border-color:#ffae66"></span> {{ $t('neighbor.fm.mesh') }}</div>
|
||||
<div class="fm-lrow" style="color:#7e90b6;margin-top:5px;font-size:10px">{{ $t('neighbor.fm.whorl') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ const mapId = (injectedInstanceId?.value || injectedInstanceId) ||
|
|||
const lcRoot = ref(null)
|
||||
const mapContainer = ref(null)
|
||||
const appReady = ref(false)
|
||||
const statusMsg = ref('Loading people groups…')
|
||||
const statusMsg = ref(nt('neighbor.lc.loading'))
|
||||
const clusters = ref([]) // [{key,lang,country,province,scope,count,lat,lng,reached:[]}]
|
||||
const reachedAll = ref([]) // flat reached list with placement coords
|
||||
const selectedKey = ref(null)
|
||||
|
|
@ -382,6 +382,8 @@ function onMove(ev) { if (tip.value.show) { tip.value.x = ev.clientX; tip.value.
|
|||
// adminUrl/dataUrl/dataBase still override live (loadJSON below).
|
||||
import bakedReached from './data/reached-neighbors.json'
|
||||
import bakedAdmin1 from './data/admin1-membership.json'
|
||||
import { useNeighborT } from './composables/useNeighborT.js'
|
||||
const nt = useNeighborT()
|
||||
async function loadJSON(relCandidates) {
|
||||
for (const url of relCandidates) {
|
||||
try { const r = await fetch(url); if (r.ok) return await r.json() } catch (_) {}
|
||||
|
|
@ -417,7 +419,7 @@ onMounted(async () => {
|
|||
// live unreached doxa-2000
|
||||
let records = []
|
||||
try { records = await fetchDoxa() }
|
||||
catch (e) { statusMsg.value = 'Live doxa API unreachable — ' + e.message; appReady.value = true; return }
|
||||
catch (e) { statusMsg.value = nt('neighbor.lc.apiDown', { message: e.message }); appReady.value = true; return }
|
||||
|
||||
clusters.value = buildClusters(records, adminProv)
|
||||
reachedAll.value = buildReached(reachedJson, clusters.value)
|
||||
|
|
@ -446,11 +448,11 @@ onMounted(async () => {
|
|||
})
|
||||
}
|
||||
hover(L_CL, p => `<strong>${esc(p.lang)}</strong><div class="lc-tip-sub">${esc(p.key)}</div>`
|
||||
+ `<div class="lc-tip-row"><span class="lc-tip-k">unreached</span> ${p.count} groups</div>`
|
||||
+ `<div class="lc-tip-row"><span class="lc-tip-k">${nt('neighbor.unreached')}</span> ${nt('neighbor.groups', { n: p.count })}</div>`
|
||||
+ `<div class="lc-tip-row"><span class="lc-tip-k">reached</span> ${p.hasReach ? 'matching neighbors ✓' : 'none found'}</div>`
|
||||
+ `<div class="lc-tip-row" style="color:#9fb3d9">click → bounded set + flower</div>`)
|
||||
hover(L_RE, p => `<strong>${esc(p.name)}</strong><div class="lc-tip-sub">${esc(p.country)} · ${esc(p.lang)}</div>`
|
||||
+ `<div class="lc-tip-row"><span class="lc-tip-k">reached</span> ${Math.round(p.pct)}% Christian</div>`)
|
||||
+ `<div class="lc-tip-row"><span class="lc-tip-k">${nt('neighbor.reached')}</span> ${nt('neighbor.pctChristian', { n: Math.round(p.pct) })}</div>`)
|
||||
}
|
||||
if (m?.isStyleLoaded?.()) wire()
|
||||
else m?.once?.('load', wire)
|
||||
|
|
@ -524,19 +526,19 @@ useShadowStyles(`
|
|||
|
||||
<!-- top bar -->
|
||||
<div class="lc-top">
|
||||
<span class="lc-title">My UPG Neighbor · Language Clusters</span>
|
||||
<span class="lc-title">{{ $t('neighbor.title.langClusters') }}</span>
|
||||
<span v-if="appReady" class="lc-stats">
|
||||
<b>{{ stats.clusters }}</b> language clusters · <b>{{ stats.pgs }}</b> unreached<br>
|
||||
<b>{{ stats.provinces }}</b> IN/CN provinces · <b>{{ stats.withReach }}</b> with reached match
|
||||
{{ $t('neighbor.lc.clusters') }}: <b>{{ stats.clusters }}</b> · {{ $t('neighbor.lc.pgs') }}: <b>{{ stats.pgs }}</b><br>
|
||||
{{ $t('neighbor.lc.provinces') }}: <b>{{ stats.provinces }}</b> · {{ $t('neighbor.lc.withReach') }}: <b>{{ stats.withReach }}</b>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- legend -->
|
||||
<div v-if="appReady" class="lc-legend">
|
||||
<h4>Bounded sets</h4>
|
||||
<div class="lc-lrow"><span class="lc-dot" :style="{ background: C_RED }"></span> Unreached language cluster (size = #groups)</div>
|
||||
<div class="lc-lrow"><span class="lc-dot" :style="{ background: reachedColor(80) }"></span> Reached neighbor (matched by language)</div>
|
||||
<div class="lc-lrow" style="color:#6b7280;font-size:10px;margin-top:4px">green ring = cluster has a reached match · click a cluster to drill</div>
|
||||
<div class="lc-lrow"><span class="lc-dot" :style="{ background: C_RED }"></span> {{ $t('neighbor.lc.legendCluster') }}</div>
|
||||
<div class="lc-lrow"><span class="lc-dot" :style="{ background: reachedColor(80) }"></span> {{ $t('neighbor.lc.legendReached') }}</div>
|
||||
<div class="lc-lrow" style="color:#6b7280;font-size:10px;margin-top:4px">{{ $t('neighbor.lc.legendHelp') }}</div>
|
||||
</div>
|
||||
|
||||
<!-- selected bounded-set panel -->
|
||||
|
|
@ -546,18 +548,18 @@ useShadowStyles(`
|
|||
<div class="lc-h-sub">{{ selected.scope === 'province' ? selected.province + ' · ' + selected.country : selected.country }}</div>
|
||||
</div>
|
||||
<div class="lc-panel-body">
|
||||
<div class="lc-sec">Bounded set — {{ selected.count }} unreached groups</div>
|
||||
<div class="lc-sec">{{ $t('neighbor.lc.setCount', { n: selected.count }) }}</div>
|
||||
<span v-for="(m, i) in selected.members.slice(0, 18)" :key="i" class="lc-chip">{{ m.name }}</span>
|
||||
<span v-if="selected.members.length > 18" class="lc-chip">+{{ selected.members.length - 18 }} more</span>
|
||||
<span v-if="selected.members.length > 18" class="lc-chip">{{ $t('neighbor.lc.more', { n: selected.members.length - 18 }) }}</span>
|
||||
|
||||
<div class="lc-sec" style="margin-top:10px">Reached neighbors (same language) — {{ selected.reached.length }}</div>
|
||||
<div v-if="!selected.reached.length" class="lc-muted">No reached people-group shares this language in the baked set. A frontier — pray for laborers (Luke 10:2).</div>
|
||||
<div class="lc-sec" style="margin-top:10px">{{ $t('neighbor.lc.reachedSame', { n: selected.reached.length }) }}</div>
|
||||
<div v-if="!selected.reached.length" class="lc-muted">{{ $t('neighbor.lc.frontier') }}</div>
|
||||
<div v-for="(r, i) in selected.reached" :key="'r'+i" class="lc-re">
|
||||
<div class="lc-re-name"><span class="lc-dot" :style="{ background: reachedColor(r.pct) }"></span>{{ r.name }}</div>
|
||||
<div class="lc-re-meta">{{ r.country }} · {{ Math.round(r.pct) }}% Christian · {{ r.lang }}</div>
|
||||
<div class="lc-re-meta">{{ r.country }} · {{ $t('neighbor.pctChristian', { n: Math.round(r.pct) }) }} · {{ r.lang }}</div>
|
||||
</div>
|
||||
|
||||
<button class="lc-drill" @click="drillToFlower">Open flower view ▸</button>
|
||||
<button class="lc-drill" @click="drillToFlower">{{ $t('neighbor.lc.openFlower') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -459,14 +459,14 @@ onBeforeUnmount(() => { destroy() })
|
|||
<div class="sn-map-area">
|
||||
<div ref="mapContainer" class="sn-map-canvas"></div>
|
||||
|
||||
<div v-if="!appReady" class="sn-loading">Loading SEND map…</div>
|
||||
<div v-if="!appReady" class="sn-loading">{{ $t('neighbor.loadingSend') }}</div>
|
||||
|
||||
<!-- Top: title + target selector -->
|
||||
<div class="sn-top">
|
||||
<span class="sn-title">My UPG Neighbor · SEND</span>
|
||||
<span class="sn-title">{{ $t('neighbor.title.send') }}</span>
|
||||
<select v-if="targetNames.length" class="sn-select"
|
||||
:value="activeTarget" @change="onSelectTarget"
|
||||
aria-label="Select unreached target country">
|
||||
:aria-label="$t('neighbor.selectTarget')">
|
||||
<option v-for="name in targetNames" :key="name" :value="name">{{ name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
@ -479,8 +479,8 @@ onBeforeUnmount(() => { destroy() })
|
|||
<div class="sn-legend-row"><span class="sn-num">3·</span><span><strong>Reached %</strong> — sender ≥10% Christian (more = more laborers)</span></div>
|
||||
<div class="sn-legend-row"><span class="sn-num">4·</span><span><strong>Lower persecution</strong> — sender from a freer place</span></div>
|
||||
<div style="border-top:1px solid #e5e7eb;margin:7px 0 5px;"></div>
|
||||
<div class="sn-legend-row"><span class="sn-dot" :style="{ background: C_ORANGE }"></span><span>Unreached target — <strong>click one</strong> to SEND-focus</span></div>
|
||||
<div class="sn-legend-row"><span class="sn-dot" :style="{ background: C_GREEN }"></span><span>Reached sender (SEND →)</span></div>
|
||||
<div class="sn-legend-row"><span class="sn-dot" :style="{ background: C_ORANGE }"></span><span>{{ $t('neighbor.send.unreachedTarget') }} <strong>{{ $t('neighbor.send.clickOne') }}</strong> {{ $t('neighbor.send.toFocus') }}</span></div>
|
||||
<div class="sn-legend-row"><span class="sn-dot" :style="{ background: C_GREEN }"></span><span>{{ $t('neighbor.send.reachedSender') }}</span></div>
|
||||
</div>
|
||||
|
||||
<!-- Right: worked sender table for the selected target -->
|
||||
|
|
@ -499,7 +499,7 @@ onBeforeUnmount(() => { destroy() })
|
|||
{{ n.name }}
|
||||
</div>
|
||||
<div class="sn-sender-meta">
|
||||
<span class="sn-chip pct">{{ Math.round(n.pct_christian || 0) }}% Christian</span>
|
||||
<span class="sn-chip pct">{{ $t('neighbor.pctChristian', { n: Math.round(n.pct_christian || 0) }) }}</span>
|
||||
<span class="sn-chip bridge">{{ n.bridge }}</span>
|
||||
<span class="sn-chip adj">{{ n.adjacency }}</span>
|
||||
<span class="sn-chip">{{ n.lang }}</span>
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ import SendMap from './src/send-map.vue'
|
|||
import FlowerMesh from './src/flower-mesh.vue'
|
||||
import LangCluster from './src/lang-cluster.vue'
|
||||
import FlowerClusters from './src/cockpit/FlowerClusters.vue'
|
||||
import { useNeighborT } from './src/composables/useNeighborT.js'
|
||||
const nt = useNeighborT()
|
||||
|
||||
const profileConfig = inject('profileConfig')
|
||||
const cfg = computed(() => profileConfig?.value || {})
|
||||
|
|
@ -82,17 +84,18 @@ useShadowStyles(`
|
|||
@media (max-width:640px){ .dun-hint{ display:none; } .dun-brand{ display:none; } }
|
||||
`, 'upg-neighbor')
|
||||
|
||||
const activeHint = computed(() => VIEWS.find(v => v.key === view.value)?.hint || '')
|
||||
const VIEW_KEY = { 'cockpit': 'cockpit', 'send-map': 'sendMap', 'flower-mesh': 'flowerMesh', 'lang-cluster': 'langCluster', 'flowers': 'flowers' }
|
||||
const activeHint = computed(() => nt('neighbor.hints.' + (VIEW_KEY[view.value] || 'sendMap')))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="rootEl" class="dun-root">
|
||||
<!-- view-switcher -->
|
||||
<div class="dun-bar">
|
||||
<span class="dun-brand">My UPG Neighbors</span>
|
||||
<div class="dun-seg" role="tablist" aria-label="Choose a view">
|
||||
<span class="dun-brand">{{ $t('neighbor.brand') }}</span>
|
||||
<div class="dun-seg" role="tablist" :aria-label="$t('neighbor.chooseView')">
|
||||
<button v-for="v in VIEWS" :key="v.key" role="tab" :aria-selected="view === v.key"
|
||||
:class="{ on: view === v.key }" @click="setView(v.key)">{{ v.label }}</button>
|
||||
:class="{ on: view === v.key }" @click="setView(v.key)">{{ $t('neighbor.views.' + VIEW_KEY[v.key]) }}</button>
|
||||
</div>
|
||||
<span class="dun-hint">{{ activeHint }}</span>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue