i18n work in rendering context (WIP) (#1592)
This commit is contained in:
parent
2ce5bbd0d8
commit
a111989bb4
|
@ -42,6 +42,7 @@ import javax.annotation.Nullable;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -50,7 +51,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
public abstract class BaseDateTimeType extends PrimitiveType<Date> {
|
public abstract class BaseDateTimeType extends PrimitiveType<Date> {
|
||||||
|
|
||||||
static final long NANOS_PER_MILLIS = 1000000L;
|
static final long NANOS_PER_MILLIS = 1000000L;
|
||||||
|
|
||||||
static final long NANOS_PER_SECOND = 1000000000L;
|
static final long NANOS_PER_SECOND = 1000000000L;
|
||||||
private static final Map<String, TimeZone> timezoneCache = new ConcurrentHashMap<>();
|
private static final Map<String, TimeZone> timezoneCache = new ConcurrentHashMap<>();
|
||||||
|
@ -816,9 +817,14 @@ public abstract class BaseDateTimeType extends PrimitiveType<Date> {
|
||||||
* {@link #toHumanDisplayLocalTimezone()} instead.
|
* {@link #toHumanDisplayLocalTimezone()} instead.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public String toHumanDisplay() {
|
public String toHumanDisplay() {
|
||||||
return DateTimeUtil.toHumanDisplay(getTimeZone(), getPrecision(), getValue(), getValueAsString());
|
return DateTimeUtil.toHumanDisplay(getTimeZone(), getPrecision(), getValue(), getValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toHumanDisplay(Locale locale) {
|
||||||
|
return DateTimeUtil.toHumanDisplay(locale, getTimeZone(), getPrecision(), getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a human readable version of this date/time using the system local format, converted to the local timezone
|
* Returns a human readable version of this date/time using the system local format, converted to the local timezone
|
||||||
|
|
|
@ -24,8 +24,11 @@ import org.hl7.fhir.r5.model.Coding;
|
||||||
import org.hl7.fhir.r5.model.Enumeration;
|
import org.hl7.fhir.r5.model.Enumeration;
|
||||||
import org.hl7.fhir.r5.model.Extension;
|
import org.hl7.fhir.r5.model.Extension;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
|
import org.hl7.fhir.r5.model.StringType;
|
||||||
|
import org.hl7.fhir.r5.renderers.CodeSystemRenderer.Translateable;
|
||||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext.MultiLanguagePolicy;
|
||||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator;
|
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator;
|
||||||
|
@ -38,6 +41,27 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
public class CodeSystemRenderer extends TerminologyRenderer {
|
public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
|
public class Translateable {
|
||||||
|
|
||||||
|
private String lang;
|
||||||
|
private StringType value;
|
||||||
|
|
||||||
|
public Translateable(String lang, StringType value) {
|
||||||
|
this.lang = lang;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLang() {
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringType getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Boolean doMarkdown = null;
|
private Boolean doMarkdown = null;
|
||||||
|
|
||||||
public CodeSystemRenderer(RenderingContext context) {
|
public CodeSystemRenderer(RenderingContext context) {
|
||||||
|
@ -426,34 +450,47 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
if (hasDefinitions) {
|
if (hasDefinitions) {
|
||||||
td = tr.td();
|
td = tr.td();
|
||||||
if (c != null &&c.hasDefinitionElement()) {
|
if (c != null &&c.hasDefinitionElement()) {
|
||||||
if (getContext().getLang() == null) {
|
// translations of the definition might come from either the translation extension, or from the designations
|
||||||
if (hasMarkdownInDefinitions(cs)) {
|
StringType defn = context.getTranslatedElement(c.getDefinitionElement());
|
||||||
addMarkdown(renderStatusDiv(c.getDefinitionElement(), td), c.getDefinition());
|
boolean sl = false;
|
||||||
} else {
|
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
|
||||||
renderStatus(c.getDefinitionElement(), td).addText(c.getDefinition());
|
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue())) {
|
||||||
|
sl = true;
|
||||||
}
|
}
|
||||||
} else if (getContext().getLang().equals("*")) {
|
}
|
||||||
boolean sl = false;
|
|
||||||
for (ConceptDefinitionDesignationComponent cd : c.getDesignation())
|
if (getContext().getMultiLanguagePolicy() == MultiLanguagePolicy.NONE && (sl || ToolingExtensions.hasLanguageTranslations(defn))) {
|
||||||
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue()))
|
if (hasMarkdownInDefinitions(cs)) {
|
||||||
sl = true;
|
addMarkdown(renderStatusDiv(defn, td), defn.asStringValue());
|
||||||
td.addText((sl ? cs.getLanguage("en")+": " : ""));
|
} else {
|
||||||
if (hasMarkdownInDefinitions(cs))
|
renderStatus(defn, td).addText(defn.asStringValue());
|
||||||
addMarkdown(renderStatusDiv(c.getDefinitionElement(), td), c.getDefinition());
|
}
|
||||||
else
|
} else {
|
||||||
renderStatus(c.getDefinitionElement(), td).addText(c.getDefinition());
|
List<Translateable> list = new ArrayList<>();
|
||||||
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
|
list.add(new Translateable(cs.getLanguage(), defn));
|
||||||
|
for (Extension ext : defn.getExtensionsByUrl(ToolingExtensions.EXT_TRANSLATION)) {
|
||||||
|
list.add(new Translateable(ext.getExtensionString("lang"), ext.getExtensionByUrl("content").getValueStringType()));
|
||||||
|
}
|
||||||
|
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
|
||||||
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue())) {
|
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue())) {
|
||||||
td.br();
|
list.add(new Translateable(cd.getLanguage(), cd.getValueElement()));
|
||||||
td.addText(cd.getLanguage()+": "+cd.getValue());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) {
|
boolean first = true;
|
||||||
renderStatus(c.getDefinitionElement(), td).addText(c.getDefinition());
|
for (Translateable ti : list) {
|
||||||
} else {
|
if (first) {
|
||||||
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
|
first = false;
|
||||||
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && cd.getLanguage().equals(getContext().getLang())) {
|
} else {
|
||||||
td.addText(cd.getValue());
|
td.br();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ti.lang != null) {
|
||||||
|
td.addText(ti.lang + ": ");
|
||||||
|
}
|
||||||
|
if (hasMarkdownInDefinitions(cs)) {
|
||||||
|
addMarkdown(renderStatusDiv(ti.getValue(), td), ti.getValue().asStringValue());
|
||||||
|
} else {
|
||||||
|
renderStatus(ti.getValue(), td).addText(ti.getValue().asStringValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,7 +346,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
if (JurisdictionUtilities.isJurisdiction(system)) {
|
if (JurisdictionUtilities.isJurisdiction(system)) {
|
||||||
return JurisdictionUtilities.displayJurisdiction(system+"#"+code);
|
return JurisdictionUtilities.displayJurisdiction(system+"#"+code);
|
||||||
}
|
}
|
||||||
ValidationResult t = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions().withLanguage(context.getLang()).withVersionFlexible(true), system, version, code, null);
|
ValidationResult t = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions().withLanguage(context.getLocale().toString()).withVersionFlexible(true), system, version, code, null);
|
||||||
|
|
||||||
if (t != null && t.getDisplay() != null)
|
if (t != null && t.getDisplay() != null)
|
||||||
return t.getDisplay();
|
return t.getDisplay();
|
||||||
|
|
|
@ -843,8 +843,8 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void markLanguage(XhtmlNode x) {
|
public void markLanguage(XhtmlNode x) {
|
||||||
x.setAttribute("lang", context.getLang());
|
x.setAttribute("lang", context.getLocale().toString());
|
||||||
x.setAttribute("xml:lang", context.getLang());
|
x.setAttribute("xml:lang", context.getLocale().toString());
|
||||||
x.addTag(0, "hr");
|
x.addTag(0, "hr");
|
||||||
x.addTag(0, "p").b().tx(context.getLocale().getDisplayName());
|
x.addTag(0, "p").b().tx(context.getLocale().getDisplayName());
|
||||||
x.addTag(0, "hr");
|
x.addTag(0, "hr");
|
||||||
|
|
|
@ -6,9 +6,11 @@ import java.time.ZoneId;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
@ -18,11 +20,8 @@ import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.elementmodel.Element;
|
import org.hl7.fhir.r5.elementmodel.Element;
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
import org.hl7.fhir.r5.model.BaseDateTimeType;
|
|
||||||
import org.hl7.fhir.r5.model.DateTimeType;
|
|
||||||
import org.hl7.fhir.r5.model.DomainResource;
|
import org.hl7.fhir.r5.model.DomainResource;
|
||||||
import org.hl7.fhir.r5.model.Enumeration;
|
import org.hl7.fhir.r5.model.Enumeration;
|
||||||
import org.hl7.fhir.r5.model.Extension;
|
|
||||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||||
import org.hl7.fhir.r5.model.StringType;
|
import org.hl7.fhir.r5.model.StringType;
|
||||||
import org.hl7.fhir.r5.renderers.utils.Resolver.IReferenceResolver;
|
import org.hl7.fhir.r5.renderers.utils.Resolver.IReferenceResolver;
|
||||||
|
@ -36,6 +35,40 @@ import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.i18n.RenderingI18nContext;
|
import org.hl7.fhir.utilities.i18n.RenderingI18nContext;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Managing Language when rendering
|
||||||
|
*
|
||||||
|
* You can specify a language to use when rendering resources by setting the setLocale() on
|
||||||
|
* the super class. The locale drives the following:
|
||||||
|
* - choice of java supplied rendering phrase, if translations are provided for the locale
|
||||||
|
* - integer and date formats used (but see below for date formats)
|
||||||
|
* - automatic translation of coded values, if language supplements are available
|
||||||
|
* - choosing text representation considering the FHIR translation extension
|
||||||
|
*
|
||||||
|
* By default, the locale is null, and the default locale for the underlying system is used.
|
||||||
|
* If you set locale to a specific value, then that value will be used instead of the default locale.
|
||||||
|
*
|
||||||
|
* By default, only a single language is rendered, based on the locale. Where resources contain
|
||||||
|
* multiple language content (designations in CodeSystem and ValueSet, or using the translation
|
||||||
|
* extension), you can control what languages are presented using the properties multiLanguagePolicy
|
||||||
|
* and languages
|
||||||
|
* - multiLanguagePolicy: NONE (default), DESIGNATIONS, ALL
|
||||||
|
* - languages: a list of allowed languages. Default is empty which means all languages in scope via multiLanguagePolicy
|
||||||
|
*
|
||||||
|
* Managing Date/Time Formatting
|
||||||
|
*
|
||||||
|
* This class has multiple parameters that influence date/time formatting when rendering resources
|
||||||
|
*
|
||||||
|
* - The default rendering is using the default java locale as above
|
||||||
|
* - If you setLocale() to something, then the defaults for the locale will be used
|
||||||
|
* - Else you can set the values of dateTimeFormat, dateFormat, dateYearFormat and dateYearMonthFormat
|
||||||
|
*
|
||||||
|
* If you set the value of locale, the values of dateTimeFormat, dateFormat, dateYearFormat and dateYearMonthFormat are
|
||||||
|
* reset to the system defaults
|
||||||
|
*
|
||||||
|
* Timezones: by default, date/times are rendered in their source timezone
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class RenderingContext extends RenderingI18nContext {
|
public class RenderingContext extends RenderingI18nContext {
|
||||||
|
|
||||||
// provides liquid templates, if they are available for the content
|
// provides liquid templates, if they are available for the content
|
||||||
|
@ -176,6 +209,12 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum MultiLanguagePolicy {
|
||||||
|
NONE, // ONLY render the language in the locale
|
||||||
|
DESIGNATIONS, // in addition to the locale language, render designations from other languages (eg. as found in code systems and value sets
|
||||||
|
ALL // in addition to translations in designations, look for an render translations (WIP)
|
||||||
|
}
|
||||||
|
|
||||||
private IWorkerContext worker;
|
private IWorkerContext worker;
|
||||||
private MarkDownProcessor markdown;
|
private MarkDownProcessor markdown;
|
||||||
private ResourceRendererMode mode;
|
private ResourceRendererMode mode;
|
||||||
|
@ -185,7 +224,15 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
private IEvaluationContext services;
|
private IEvaluationContext services;
|
||||||
private ITypeParser parser;
|
private ITypeParser parser;
|
||||||
|
|
||||||
private String lang;
|
// i18n related fields
|
||||||
|
private MultiLanguagePolicy multiLanguagePolicy = MultiLanguagePolicy.NONE;
|
||||||
|
private Set<String> allowedLanguages = new HashSet<>();
|
||||||
|
private ZoneId timeZoneId;
|
||||||
|
private DateTimeFormatter dateTimeFormat;
|
||||||
|
private DateTimeFormatter dateFormat;
|
||||||
|
private DateTimeFormatter dateYearFormat;
|
||||||
|
private DateTimeFormatter dateYearMonthFormat;
|
||||||
|
|
||||||
private String localPrefix; // relative link within local context
|
private String localPrefix; // relative link within local context
|
||||||
private int headerLevelContext;
|
private int headerLevelContext;
|
||||||
private boolean canonicalUrlsAsLinks;
|
private boolean canonicalUrlsAsLinks;
|
||||||
|
@ -212,11 +259,6 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
private boolean showComments = false;
|
private boolean showComments = false;
|
||||||
|
|
||||||
private FhirPublication targetVersion;
|
private FhirPublication targetVersion;
|
||||||
private ZoneId timeZoneId;
|
|
||||||
private DateTimeFormatter dateTimeFormat;
|
|
||||||
private DateTimeFormatter dateFormat;
|
|
||||||
private DateTimeFormatter dateYearFormat;
|
|
||||||
private DateTimeFormatter dateYearMonthFormat;
|
|
||||||
private boolean copyButton;
|
private boolean copyButton;
|
||||||
private ProfileKnowledgeProvider pkp;
|
private ProfileKnowledgeProvider pkp;
|
||||||
private String changeVersion;
|
private String changeVersion;
|
||||||
|
@ -233,13 +275,13 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
* @param markdown - appropriate markdown processing engine
|
* @param markdown - appropriate markdown processing engine
|
||||||
* @param terminologyServiceOptions - options to use when looking up codes
|
* @param terminologyServiceOptions - options to use when looking up codes
|
||||||
* @param specLink - path to FHIR specification
|
* @param specLink - path to FHIR specification
|
||||||
* @param lang - langauage to render in
|
* @param locale - i18n for rendering
|
||||||
*/
|
*/
|
||||||
public RenderingContext(IWorkerContext worker, MarkDownProcessor markdown, ValidationOptions terminologyServiceOptions, String specLink, String localPrefix, String lang, ResourceRendererMode mode, GenerationRules rules) {
|
public RenderingContext(IWorkerContext worker, MarkDownProcessor markdown, ValidationOptions terminologyServiceOptions, String specLink, String localPrefix, Locale locale, ResourceRendererMode mode, GenerationRules rules) {
|
||||||
super();
|
super();
|
||||||
this.worker = worker;
|
this.worker = worker;
|
||||||
this.markdown = markdown;
|
this.markdown = markdown;
|
||||||
this.lang = lang;
|
this.locale = locale;
|
||||||
this.links.put(KnownLinkType.SPEC, specLink);
|
this.links.put(KnownLinkType.SPEC, specLink);
|
||||||
this.localPrefix = localPrefix;
|
this.localPrefix = localPrefix;
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
@ -247,12 +289,10 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
if (terminologyServiceOptions != null) {
|
if (terminologyServiceOptions != null) {
|
||||||
this.terminologyServiceOptions = terminologyServiceOptions;
|
this.terminologyServiceOptions = terminologyServiceOptions;
|
||||||
}
|
}
|
||||||
// default to US locale - discussion here: https://github.com/hapifhir/org.hl7.fhir.core/issues/666
|
|
||||||
this.locale = new Locale.Builder().setLanguageTag("en-US").build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderingContext copy() {
|
public RenderingContext copy() {
|
||||||
RenderingContext res = new RenderingContext(worker, markdown, terminologyServiceOptions, getLink(KnownLinkType.SPEC), localPrefix, lang, mode, rules);
|
RenderingContext res = new RenderingContext(worker, markdown, terminologyServiceOptions, getLink(KnownLinkType.SPEC), localPrefix, locale, mode, rules);
|
||||||
|
|
||||||
res.resolver = resolver;
|
res.resolver = resolver;
|
||||||
res.templateProvider = templateProvider;
|
res.templateProvider = templateProvider;
|
||||||
|
@ -291,6 +331,8 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
|
|
||||||
res.terminologyServiceOptions = terminologyServiceOptions.copy();
|
res.terminologyServiceOptions = terminologyServiceOptions.copy();
|
||||||
res.typeMap.putAll(typeMap);
|
res.typeMap.putAll(typeMap);
|
||||||
|
res.multiLanguagePolicy = multiLanguagePolicy;
|
||||||
|
res.allowedLanguages.addAll(allowedLanguages);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,8 +372,16 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
return markdown;
|
return markdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLang() {
|
public MultiLanguagePolicy getMultiLanguagePolicy() {
|
||||||
return lang;
|
return multiLanguagePolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMultiLanguagePolicy(MultiLanguagePolicy multiLanguagePolicy) {
|
||||||
|
this.multiLanguagePolicy = multiLanguagePolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getAllowedLanguages() {
|
||||||
|
return allowedLanguages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLocalPrefix() {
|
public String getLocalPrefix() {
|
||||||
|
@ -502,14 +552,6 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderingContext setLang(String lang) {
|
|
||||||
this.lang = lang;
|
|
||||||
if (lang != null) {
|
|
||||||
setLocale(new Locale(lang));
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RenderingContext setLocalPrefix(String localPrefix) {
|
public RenderingContext setLocalPrefix(String localPrefix) {
|
||||||
this.localPrefix = localPrefix;
|
this.localPrefix = localPrefix;
|
||||||
return this;
|
return this;
|
||||||
|
@ -746,8 +788,8 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
|
|
||||||
|
|
||||||
public String getTranslated(PrimitiveType<?> t) {
|
public String getTranslated(PrimitiveType<?> t) {
|
||||||
if (lang != null) {
|
if (locale != null) {
|
||||||
String v = ToolingExtensions.getLanguageTranslation(t, lang);
|
String v = ToolingExtensions.getLanguageTranslation(t, locale.toString());
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -755,18 +797,32 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
return t.asStringValue();
|
return t.asStringValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StringType getTranslatedElement(PrimitiveType<?> t) {
|
||||||
|
if (locale != null) {
|
||||||
|
StringType v = ToolingExtensions.getLanguageTranslationElement(t, locale.toString());
|
||||||
|
if (v != null) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t instanceof StringType) {
|
||||||
|
return (StringType) t;
|
||||||
|
} else {
|
||||||
|
return new StringType(t.asStringValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getTranslatedCode(Base b, String codeSystem) {
|
public String getTranslatedCode(Base b, String codeSystem) {
|
||||||
|
|
||||||
if (b instanceof org.hl7.fhir.r5.model.Element) {
|
if (b instanceof org.hl7.fhir.r5.model.Element) {
|
||||||
org.hl7.fhir.r5.model.Element e = (org.hl7.fhir.r5.model.Element) b;
|
org.hl7.fhir.r5.model.Element e = (org.hl7.fhir.r5.model.Element) b;
|
||||||
if (lang != null) {
|
if (locale != null) {
|
||||||
String v = ToolingExtensions.getLanguageTranslation(e, lang);
|
String v = ToolingExtensions.getLanguageTranslation(e, locale.toString());
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
// no? then see if the tx service can translate it for us
|
// no? then see if the tx service can translate it for us
|
||||||
try {
|
try {
|
||||||
ValidationResult t = getContext().validateCode(getTerminologyServiceOptions().withLanguage(lang).withVersionFlexible(true),
|
ValidationResult t = getContext().validateCode(getTerminologyServiceOptions().withLanguage(locale.toString()).withVersionFlexible(true),
|
||||||
codeSystem, null, e.primitiveValue(), null);
|
codeSystem, null, e.primitiveValue(), null);
|
||||||
if (t.isOk() && t.getDisplay() != null) {
|
if (t.isOk() && t.getDisplay() != null) {
|
||||||
return t.getDisplay();
|
return t.getDisplay();
|
||||||
|
@ -788,14 +844,14 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTranslatedCode(Enumeration<?> e, String codeSystem) {
|
public String getTranslatedCode(Enumeration<?> e, String codeSystem) {
|
||||||
if (lang != null) {
|
if (locale != null) {
|
||||||
String v = ToolingExtensions.getLanguageTranslation(e, lang);
|
String v = ToolingExtensions.getLanguageTranslation(e, locale.toString());
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
// no? then see if the tx service can translate it for us
|
// no? then see if the tx service can translate it for us
|
||||||
try {
|
try {
|
||||||
ValidationResult t = getContext().validateCode(getTerminologyServiceOptions().withLanguage(lang).withVersionFlexible(true),
|
ValidationResult t = getContext().validateCode(getTerminologyServiceOptions().withLanguage(locale.toString()).withVersionFlexible(true),
|
||||||
codeSystem, null, e.getCode(), null);
|
codeSystem, null, e.getCode(), null);
|
||||||
if (t.isOk() && t.getDisplay() != null) {
|
if (t.isOk() && t.getDisplay() != null) {
|
||||||
return t.getDisplay();
|
return t.getDisplay();
|
||||||
|
@ -818,14 +874,14 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTranslatedCode(Element e, String codeSystem) {
|
public String getTranslatedCode(Element e, String codeSystem) {
|
||||||
if (lang != null) {
|
if (locale != null) {
|
||||||
// first we look through the translation extensions
|
// first we look through the translation extensions
|
||||||
for (Element ext : e.getChildrenByName("extension")) {
|
for (Element ext : e.getChildrenByName("extension")) {
|
||||||
String url = ext.getNamedChildValue("url");
|
String url = ext.getNamedChildValue("url");
|
||||||
if (url.equals(ToolingExtensions.EXT_TRANSLATION)) {
|
if (url.equals(ToolingExtensions.EXT_TRANSLATION)) {
|
||||||
Base e1 = ext.getExtensionValue("lang");
|
Base e1 = ext.getExtensionValue("lang");
|
||||||
|
|
||||||
if (e1 != null && e1.primitiveValue() != null && e1.primitiveValue().equals(lang)) {
|
if (e1 != null && e1.primitiveValue() != null && e1.primitiveValue().equals(locale.toString())) {
|
||||||
e1 = ext.getExtensionValue("content");
|
e1 = ext.getExtensionValue("content");
|
||||||
if (e1 != null && e1.isPrimitive()) {
|
if (e1 != null && e1.isPrimitive()) {
|
||||||
return e1.primitiveValue();
|
return e1.primitiveValue();
|
||||||
|
@ -835,7 +891,7 @@ public class RenderingContext extends RenderingI18nContext {
|
||||||
}
|
}
|
||||||
// no? then see if the tx service can translate it for us
|
// no? then see if the tx service can translate it for us
|
||||||
try {
|
try {
|
||||||
ValidationResult t = getContext().validateCode(getTerminologyServiceOptions().withLanguage(lang).withVersionFlexible(true),
|
ValidationResult t = getContext().validateCode(getTerminologyServiceOptions().withLanguage(locale.toString()).withVersionFlexible(true),
|
||||||
codeSystem, null, e.primitiveValue(), null);
|
codeSystem, null, e.primitiveValue(), null);
|
||||||
if (t.isOk() && t.getDisplay() != null) {
|
if (t.isOk() && t.getDisplay() != null) {
|
||||||
return t.getDisplay();
|
return t.getDisplay();
|
||||||
|
|
|
@ -776,6 +776,15 @@ public class ToolingExtensions {
|
||||||
// throw new Error("Attempt to assign multiple OIDs to value set "+vs.getName()+" ("+vs.getUrl()+"). Has "+readStringExtension(vs, EXT_OID)+", trying to add "+oid);
|
// throw new Error("Attempt to assign multiple OIDs to value set "+vs.getName()+" ("+vs.getUrl()+"). Has "+readStringExtension(vs, EXT_OID)+", trying to add "+oid);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
public static boolean hasLanguageTranslations(Element element) {
|
||||||
|
for (Extension e : element.getExtension()) {
|
||||||
|
if (e.getUrl().equals(EXT_TRANSLATION)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean hasLanguageTranslation(Element element, String lang) {
|
public static boolean hasLanguageTranslation(Element element, String lang) {
|
||||||
for (Extension e : element.getExtension()) {
|
for (Extension e : element.getExtension()) {
|
||||||
if (e.getUrl().equals(EXT_TRANSLATION)) {
|
if (e.getUrl().equals(EXT_TRANSLATION)) {
|
||||||
|
@ -802,6 +811,20 @@ public class ToolingExtensions {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StringType getLanguageTranslationElement(Element element, String lang) {
|
||||||
|
for (Extension e : element.getExtension()) {
|
||||||
|
if (e.getUrl().equals(EXT_TRANSLATION)) {
|
||||||
|
Extension e1 = ExtensionHelper.getExtension(e, "lang");
|
||||||
|
|
||||||
|
if (e1 != null && e1.getValue() != null && e1.getValue() instanceof CodeType && ((CodeType) e1.getValue()).getValue().equals(lang)) {
|
||||||
|
e1 = ExtensionHelper.getExtension(e, "content");
|
||||||
|
return ((StringType) e1.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static void addLanguageTranslation(Element element, String lang, String value) {
|
public static void addLanguageTranslation(Element element, String lang, String value) {
|
||||||
if (Utilities.noString(lang) || Utilities.noString(value))
|
if (Utilities.noString(lang) || Utilities.noString(value))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.hl7.fhir.utilities;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.apache.commons.lang3.time.FastDateFormat;
|
import org.apache.commons.lang3.time.FastDateFormat;
|
||||||
|
@ -42,4 +43,25 @@ public class DateTimeUtil {
|
||||||
return ourHumanDateTimeFormat.format(theValue);
|
return ourHumanDateTimeFormat.format(theValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String toHumanDisplay(Locale locale, TimeZone theTimeZone, TemporalPrecisionEnum thePrecision, Date theValue) {
|
||||||
|
Calendar value = theTimeZone != null ? Calendar.getInstance(theTimeZone) : Calendar.getInstance();
|
||||||
|
value.setTime(theValue);
|
||||||
|
|
||||||
|
FastDateFormat dateFormat = FastDateFormat.getDateInstance(FastDateFormat.MEDIUM, locale);
|
||||||
|
FastDateFormat dateTimeFormat = FastDateFormat.getDateTimeInstance(FastDateFormat.MEDIUM, FastDateFormat.MEDIUM, locale);
|
||||||
|
|
||||||
|
switch (thePrecision) {
|
||||||
|
case YEAR:
|
||||||
|
case MONTH:
|
||||||
|
case DAY:
|
||||||
|
return dateFormat.format(value);
|
||||||
|
case MILLI:
|
||||||
|
case SECOND:
|
||||||
|
default:
|
||||||
|
return dateTimeFormat.format(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ public abstract class I18nBase {
|
||||||
if (Objects.nonNull(locale)) {
|
if (Objects.nonNull(locale)) {
|
||||||
return locale;
|
return locale;
|
||||||
} else {
|
} else {
|
||||||
return Locale.US;
|
return Locale.getDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue