Improved language support for IG development
This commit is contained in:
parent
b2e3c261e4
commit
99ea673b91
|
@ -1342,6 +1342,23 @@ public class Element extends Base implements NamedItem {
|
||||||
children.add(ne);
|
children.add(ne);
|
||||||
return ne;
|
return ne;
|
||||||
}
|
}
|
||||||
|
// polymorphic support
|
||||||
|
if (p.getName().endsWith("[x]")) {
|
||||||
|
String base = p.getName().substring(0, p.getName().length()-3);
|
||||||
|
|
||||||
|
if (name.startsWith(base)) {
|
||||||
|
String type = name.substring(base.length());
|
||||||
|
if (p.getContextUtils().isPrimitiveType(Utilities.uncapitalize(type))) {
|
||||||
|
type = Utilities.uncapitalize(type);
|
||||||
|
}
|
||||||
|
if (p.canBeType(type)) {
|
||||||
|
Element ne = new Element(name, p).setFormat(format);
|
||||||
|
ne.setType(type);
|
||||||
|
children.add(ne);
|
||||||
|
return ne;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("Unrecognised property '"+name+"' on "+this.name);
|
throw new Error("Unrecognised property '"+name+"' on "+this.name);
|
||||||
|
|
|
@ -24,6 +24,10 @@ import org.hl7.fhir.utilities.i18n.LanguageFileProducer;
|
||||||
import org.hl7.fhir.utilities.i18n.LanguageFileProducer.LanguageProducerLanguageSession;
|
import org.hl7.fhir.utilities.i18n.LanguageFileProducer.LanguageProducerLanguageSession;
|
||||||
import org.hl7.fhir.utilities.i18n.LanguageFileProducer.TextUnit;
|
import org.hl7.fhir.utilities.i18n.LanguageFileProducer.TextUnit;
|
||||||
import org.hl7.fhir.utilities.i18n.LanguageFileProducer.TranslationUnit;
|
import org.hl7.fhir.utilities.i18n.LanguageFileProducer.TranslationUnit;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* in here:
|
* in here:
|
||||||
|
@ -78,7 +82,6 @@ public class LanguageUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String contextForElement(Element element) {
|
private String contextForElement(Element element) {
|
||||||
throw new Error("Not done yet");
|
throw new Error("Not done yet");
|
||||||
}
|
}
|
||||||
|
@ -110,7 +113,7 @@ public class LanguageUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTranslatable(Element element) {
|
private boolean isTranslatable(Element element) {
|
||||||
return element.getProperty().isTranslatable() && !Utilities.existsInList(pathForElement(element), "CanonicalResource.version");
|
return element.getProperty().isTranslatable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String pathForElement(Element element) {
|
private String pathForElement(Element element) {
|
||||||
|
@ -132,11 +135,24 @@ public class LanguageUtils {
|
||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int importFromTranslations(Element resource, Set<TranslationUnit> translations) {
|
|
||||||
return importFromTranslations(null, resource, translations);
|
public int importFromTranslations(Element resource, List<TranslationUnit> translations) {
|
||||||
|
return importFromTranslations(null, resource, translations, new HashSet<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private int importFromTranslations(Element parent, Element element, Set<TranslationUnit> translations) {
|
public int importFromTranslations(Element resource, List<TranslationUnit> translations, List<ValidationMessage> messages) {
|
||||||
|
Set<TranslationUnit> usedUnits = new HashSet<>();
|
||||||
|
int r = importFromTranslations(null, resource, translations, usedUnits);
|
||||||
|
for (TranslationUnit t : translations) {
|
||||||
|
if (!usedUnits.contains(t)) {
|
||||||
|
messages.add(new ValidationMessage(Source.Publisher, IssueType.INFORMATIONAL, t.getId(), "Unused '"+t.getLanguage()+"' translation '"+t.getSrcText()+"' -> '"+t.getTgtText()+"'", IssueSeverity.INFORMATION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int importFromTranslations(Element parent, Element element, List<TranslationUnit> translations, Set<TranslationUnit> usedUnits) {
|
||||||
int t = 0;
|
int t = 0;
|
||||||
if (element.isPrimitive() && isTranslatable(element)) {
|
if (element.isPrimitive() && isTranslatable(element)) {
|
||||||
String base = element.primitiveValue();
|
String base = element.primitiveValue();
|
||||||
|
@ -146,13 +162,14 @@ public class LanguageUtils {
|
||||||
t++;
|
t++;
|
||||||
if (!handleAsSpecial(parent, element, translation)) {
|
if (!handleAsSpecial(parent, element, translation)) {
|
||||||
element.setTranslation(translation.getLanguage(), translation.getTgtText());
|
element.setTranslation(translation.getLanguage(), translation.getTgtText());
|
||||||
|
usedUnits.add(translation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Element c: element.getChildren()) {
|
for (Element c: element.getChildren()) {
|
||||||
if (!c.getName().equals("designation")) {
|
if (!c.getName().equals("designation")) {
|
||||||
t = t + importFromTranslations(element, c, translations);
|
t = t + importFromTranslations(element, c, translations, usedUnits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
|
@ -193,7 +210,7 @@ public class LanguageUtils {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<TranslationUnit> findTranslations(String path, String src, Set<TranslationUnit> translations) {
|
private Set<TranslationUnit> findTranslations(String path, String src, List<TranslationUnit> translations) {
|
||||||
Set<TranslationUnit> res = new HashSet<>();
|
Set<TranslationUnit> res = new HashSet<>();
|
||||||
for (TranslationUnit translation : translations) {
|
for (TranslationUnit translation : translations) {
|
||||||
if (path.equals(translation.getId()) && src.equals(translation.getSrcText())) {
|
if (path.equals(translation.getId()) && src.equals(translation.getSrcText())) {
|
||||||
|
@ -294,7 +311,7 @@ public class LanguageUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean handlesAsElement(Element element) {
|
public static boolean handlesAsElement(Element element) {
|
||||||
return false; // for now...
|
return true; // for now...
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<TranslationUnit> generateTranslations(Resource res, String lang) {
|
public static List<TranslationUnit> generateTranslations(Resource res, String lang) {
|
||||||
|
@ -334,4 +351,52 @@ public class LanguageUtils {
|
||||||
return cd.getDefinition();
|
return cd.getDefinition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<TranslationUnit> generateTranslations(Element e, String lang) {
|
||||||
|
List<TranslationUnit> list = new ArrayList<>();
|
||||||
|
generateTranslations(e, lang, list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void generateTranslations(Element e, String lang, List<TranslationUnit> list) {
|
||||||
|
if (e.getProperty().isTranslatable()) {
|
||||||
|
String id = e.getProperty().getDefinition().getPath();
|
||||||
|
String context = e.getProperty().getDefinition().getDefinition();
|
||||||
|
String src = e.primitiveValue();
|
||||||
|
String tgt = getTranslation(e, lang);
|
||||||
|
list.add(new TranslationUnit(lang, id, context, src, tgt));
|
||||||
|
}
|
||||||
|
if (e.hasChildren()) {
|
||||||
|
for (Element c : e.getChildren()) {
|
||||||
|
generateTranslations(c, lang, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getTranslation(Element e, String lang) {
|
||||||
|
if (!e.hasChildren()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (Element ext : e.getChildren()) {
|
||||||
|
if ("Extension".equals(ext.fhirType()) && "http://hl7.org/fhir/StructureDefinition/translation".equals(ext.getNamedChildValue("url"))) {
|
||||||
|
String l = null;
|
||||||
|
String v = null;
|
||||||
|
for (Element subExt : ext.getChildren()) {
|
||||||
|
if ("Extension".equals(subExt.fhirType()) && "lang".equals(subExt.getNamedChildValue("url"))) {
|
||||||
|
lang = subExt.getNamedChildValue("value");
|
||||||
|
}
|
||||||
|
if ("Extension".equals(subExt.fhirType()) && "lang".equals(subExt.getNamedChildValue("content"))) {
|
||||||
|
v = subExt.getNamedChildValue("value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lang.equals(l)) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -641,14 +641,32 @@ public class Property {
|
||||||
|
|
||||||
public boolean isTranslatable() {
|
public boolean isTranslatable() {
|
||||||
boolean ok = ToolingExtensions.readBoolExtension(definition, ToolingExtensions.EXT_TRANSLATABLE);
|
boolean ok = ToolingExtensions.readBoolExtension(definition, ToolingExtensions.EXT_TRANSLATABLE);
|
||||||
if (!ok && !Utilities.existsInList(definition.getBase().getPath(), "Reference.reference", "Coding.version", "Identifier.value", "SampledData.offsets", "SampledData.data", "ContactPoint.value")) {
|
if (!ok && !definition.getPath().endsWith(".id") && !Utilities.existsInList(definition.getBase().getPath(), "Resource.id", "Reference.reference", "Coding.version", "Identifier.value", "SampledData.offsets", "SampledData.data", "ContactPoint.value")) {
|
||||||
String t = getType();
|
String t = getType();
|
||||||
ok = Utilities.existsInList(t, "string", "markdown");
|
ok = Utilities.existsInList(t, "string", "markdown");
|
||||||
}
|
}
|
||||||
|
if (Utilities.existsInList(pathForElement(getStructure().getType(), getDefinition().getBase().getPath()), "CanonicalResource.version")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String pathForElement(String type, String path) {
|
||||||
|
// special case support for metadata elements prior to R5:
|
||||||
|
if (utils.getCanonicalResourceNames().contains(type)) {
|
||||||
|
String fp = path.replace(type+".", "CanonicalResource.");
|
||||||
|
if (Utilities.existsInList(fp,
|
||||||
|
"CanonicalResource.url", "CanonicalResource.identifier", "CanonicalResource.version", "CanonicalResource.name",
|
||||||
|
"CanonicalResource.title", "CanonicalResource.status", "CanonicalResource.experimental", "CanonicalResource.date",
|
||||||
|
"CanonicalResource.publisher", "CanonicalResource.contact", "CanonicalResource.description", "CanonicalResource.useContext",
|
||||||
|
"CanonicalResource.jurisdiction")) {
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
public String getXmlTypeName() {
|
public String getXmlTypeName() {
|
||||||
TypeRefComponent tr = type;
|
TypeRefComponent tr = type;
|
||||||
if (tr == null) {
|
if (tr == null) {
|
||||||
|
@ -678,4 +696,14 @@ public class Property {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean canBeType(String type) {
|
||||||
|
for (TypeRefComponent tr : getDefinition().getType()) {
|
||||||
|
if (type.equals(tr.getWorkingCode())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -167,13 +167,22 @@ public class PoGetTextProducer extends LanguageFileProducer {
|
||||||
if (tu.getContext1() != null) {
|
if (tu.getContext1() != null) {
|
||||||
ln(po, "#. "+tu.getContext1());
|
ln(po, "#. "+tu.getContext1());
|
||||||
}
|
}
|
||||||
ln(po, "msgid \""+tu.getSrcText()+"\"");
|
ln(po, "msgid \""+stripEoln(tu.getSrcText())+"\"");
|
||||||
ln(po, "msgstr \""+(tu.getTgtText() == null ? "" : tu.getTgtText())+"\"");
|
ln(po, "msgstr \""+(tu.getTgtText() == null ? "" : stripEoln(tu.getTgtText()))+"\"");
|
||||||
ln(po, "");
|
ln(po, "");
|
||||||
}
|
}
|
||||||
TextFile.stringToFile(po.toString(), Utilities.path(getFolder(), filename));
|
TextFile.stringToFile(po.toString(), Utilities.path(getFolder(), filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String stripEoln(String s) {
|
||||||
|
s = s.replace("\r\n\r\n", " ").replace("\n\n", " ").replace("\r\r", " ");
|
||||||
|
s = s.replace("\r\n", " ").replace("\n", " ").replace("\r", " ");
|
||||||
|
// // yes, the double escaping is intentional here - it appears necessary
|
||||||
|
// s = s.replace("\\r\\n\\r\\n", " ").replace("\\n\\n", " ").replace("\\r\\r", " ");
|
||||||
|
// s = s.replace("\\r\\n", " ").replace("\\n", " ").replace("\\r", " ");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue