Got universal strings to notify for missing translations.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
This commit is contained in:
@@ -10,6 +10,6 @@ use record::{InternalRecord, InternalRecords, Oid};
|
||||
pub use clock::Clock;
|
||||
pub use create::{CreateDoc, IndexType};
|
||||
pub use definition::{DocDef, DocFuncType};
|
||||
pub use field::{Field, FieldType};
|
||||
pub use field::{Field, FieldType, MissingTranslation};
|
||||
pub use record::{Record, Records};
|
||||
pub use session::Session;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::{ErrorID, MTTError};
|
||||
use chrono::prelude::*;
|
||||
use isolang::Language;
|
||||
use std::{
|
||||
@@ -577,10 +578,96 @@ mod paragraphs {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
struct ParagraphID {
|
||||
data: Uuid,
|
||||
}
|
||||
|
||||
impl ParagraphID {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
data: Uuid::new_v4(),
|
||||
}
|
||||
}
|
||||
|
||||
fn nil() -> Self {
|
||||
Self { data: Uuid::nil() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod paragraphids {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn are_paragraph_ids_unique() {
|
||||
let id1 = ParagraphID::new();
|
||||
let id2 = ParagraphID::new();
|
||||
assert_ne!(id1, id2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_create_nil() {
|
||||
let id = ParagraphID::nil();
|
||||
assert_eq!(id.data, Uuid::nil());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MissingTranslation {
|
||||
needs: Language,
|
||||
has: Language,
|
||||
text: String,
|
||||
}
|
||||
|
||||
impl MissingTranslation {
|
||||
fn new(needs: Language, has: Language, text: String) -> Self {
|
||||
Self {
|
||||
needs: needs,
|
||||
has: has,
|
||||
text: text,
|
||||
}
|
||||
}
|
||||
|
||||
fn needs(&self) -> Language {
|
||||
self.needs.clone()
|
||||
}
|
||||
|
||||
fn has(&self) -> Language {
|
||||
self.has.clone()
|
||||
}
|
||||
|
||||
fn text(&self) -> String {
|
||||
self.text.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod missing_translations {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn can_get_mising_translation_information() {
|
||||
let langs = [
|
||||
Language::from_639_1("en").unwrap(),
|
||||
Language::from_639_1("ja").unwrap(),
|
||||
];
|
||||
let text = Uuid::new_v4().to_string();
|
||||
let missing = MissingTranslation::new(langs[0].clone(), langs[1].clone(), text.clone());
|
||||
assert_eq!(missing.needs(), langs[0]);
|
||||
assert_eq!(missing.has(), langs[1]);
|
||||
assert_eq!(missing.text(), text);
|
||||
let missing2 = MissingTranslation::new(langs[1].clone(), langs[0].clone(), text.clone());
|
||||
assert_eq!(missing2.needs(), langs[1]);
|
||||
assert_eq!(missing2.has(), langs[0]);
|
||||
assert_eq!(missing2.text(), text);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct UniversalString {
|
||||
paragraphs: HashMap<Uuid, Paragraph>,
|
||||
revisions: Vec<Vec<Uuid>>,
|
||||
paragraphs: HashMap<ParagraphID, Paragraph>,
|
||||
revisions: Vec<Vec<ParagraphID>>,
|
||||
}
|
||||
|
||||
impl UniversalString {
|
||||
@@ -593,20 +680,36 @@ impl UniversalString {
|
||||
output
|
||||
}
|
||||
|
||||
fn get(&self, lang: &Language) -> Option<String> {
|
||||
fn get(&self, lang: &Language) -> Result<String, MTTError> {
|
||||
let latest = self.revisions.len() - 1;
|
||||
self.get_revision(latest, lang)
|
||||
}
|
||||
|
||||
fn get_revision(&self, rev_num: usize, lang: &Language) -> Option<String> {
|
||||
fn get_revision(&self, rev_num: usize, lang: &Language) -> Result<String, MTTError> {
|
||||
let mut output = "".to_string();
|
||||
let mut missing: Vec<MissingTranslation> = Vec::new();
|
||||
for id in self.revisions[rev_num].iter() {
|
||||
let paragraph = self.paragraphs.get(id).unwrap();
|
||||
let text = paragraph.get(lang).unwrap();
|
||||
let text = match paragraph.get(lang) {
|
||||
Some(data) => data,
|
||||
None => {
|
||||
let (ori_lang, text) = paragraph.get_initial();
|
||||
missing.push(MissingTranslation::new(
|
||||
lang.clone(),
|
||||
ori_lang.clone(),
|
||||
text.clone(),
|
||||
));
|
||||
""
|
||||
}
|
||||
};
|
||||
output += text;
|
||||
output += "\u{2029}";
|
||||
}
|
||||
Some(output)
|
||||
if missing.is_empty() {
|
||||
Ok(output)
|
||||
} else {
|
||||
Err(MTTError::new(ErrorID::MissingTranslation(missing)))
|
||||
}
|
||||
}
|
||||
|
||||
fn revision_count(&self) -> usize {
|
||||
@@ -617,17 +720,17 @@ impl UniversalString {
|
||||
let mut version = Vec::new();
|
||||
for paragraph in text.as_str().split("\u{2029}") {
|
||||
if paragraph != "" {
|
||||
let mut id = Uuid::nil();
|
||||
let mut id = ParagraphID::nil();
|
||||
for (key, value) in self.paragraphs.iter() {
|
||||
if ¶graph == value.get(&lang).unwrap() {
|
||||
id = key.clone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if id == Uuid::nil() {
|
||||
id = Uuid::new_v4();
|
||||
if id == ParagraphID::nil() {
|
||||
id = ParagraphID::new();
|
||||
while self.paragraphs.contains_key(&id) {
|
||||
id = Uuid::new_v4();
|
||||
id = ParagraphID::new();
|
||||
}
|
||||
self.paragraphs.insert(
|
||||
id.clone(),
|
||||
@@ -645,6 +748,7 @@ impl UniversalString {
|
||||
mod universal_strings {
|
||||
use super::*;
|
||||
use rand::random_range;
|
||||
use std::collections::HashSet;
|
||||
|
||||
const ENGLISH_DATA: [&str; 5] = ["one", "two", "three", "four", "five"];
|
||||
const JAPANESE_DATA: [&str; 5] = ["一", "二", "三", "四", "五"];
|
||||
@@ -764,4 +868,32 @@ mod universal_strings {
|
||||
assert_eq!(ustr.paragraphs.len(), expected_paragraphs, "{:?}", ustr);
|
||||
assert_eq!(ustr.get_revision(0, &lang).unwrap(), initial);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_translation_be_added() {
|
||||
let (elang, edata) = TestData::english();
|
||||
let (jlang, jdata) = TestData::japanese();
|
||||
let initial = TestData::to_input(jdata.clone());
|
||||
let mut ustr = UniversalString::new(jlang.clone(), initial.clone());
|
||||
assert_eq!(ustr.get(&jlang).unwrap(), initial);
|
||||
let err = ustr.get(&elang).unwrap_err();
|
||||
match err.get_error_ids().iter().last().unwrap() {
|
||||
ErrorID::MissingTranslation(missing) => {
|
||||
assert_eq!(
|
||||
missing.len(),
|
||||
jdata.len(),
|
||||
"should return list of translations needed"
|
||||
);
|
||||
let mut holder: HashSet<String> = jdata.iter().cloned().collect();
|
||||
for data in missing.iter() {
|
||||
assert_eq!(data.needs(), elang, "needed language is incorrect");
|
||||
assert_eq!(data.has(), jlang, "original language is incorrect");
|
||||
assert!(holder.contains(&data.text()));
|
||||
holder.remove(&data.text());
|
||||
}
|
||||
assert!(holder.is_empty(), "still had {:?}", holder);
|
||||
}
|
||||
_ => unreachable!("got {:?}, should have been needs translation", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ mod mtterror;
|
||||
pub mod name;
|
||||
mod queue;
|
||||
|
||||
pub use action::*;
|
||||
use document::{Clock, CreateDoc, Session};
|
||||
use message::{wrapper::Message, MessageAction};
|
||||
use queue::{
|
||||
@@ -18,6 +17,8 @@ use std::{
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub use action::*;
|
||||
pub use document::MissingTranslation;
|
||||
pub use mtterror::{ErrorID, MTTError};
|
||||
pub use name::{Name, NameType};
|
||||
pub use queue::data_director::{Include, Path};
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::{
|
||||
action::{Field, FieldType},
|
||||
message::MessageAction,
|
||||
name::{Name, NameType},
|
||||
MissingTranslation,
|
||||
};
|
||||
use isolang::Language;
|
||||
use std::{collections::VecDeque, error::Error, fmt};
|
||||
@@ -21,6 +22,7 @@ pub enum ErrorID {
|
||||
FieldTypeExpected(FieldType),
|
||||
IndexEntryAlreadyExists(Field),
|
||||
InvalidFieldName(Name),
|
||||
MissingTranslation(Vec<MissingTranslation>),
|
||||
NameAlreadyExists,
|
||||
NameLanguageNotUnique,
|
||||
NameNotFound(NameType),
|
||||
|
||||
Reference in New Issue
Block a user