aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java54
-rw-r--r--src/java/org/apache/fop/area/AreaTreeParser.java9
-rw-r--r--src/java/org/apache/fop/area/PageSequence.java47
-rw-r--r--src/java/org/apache/fop/fo/pagination/PageSequence.java29
-rw-r--r--src/java/org/apache/fop/fo/pagination/Root.java13
-rw-r--r--src/java/org/apache/fop/fo/properties/CommonHyphenation.java37
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java3
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFRenderer.java13
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java24
-rw-r--r--src/java/org/apache/fop/render/xml/XMLRenderer.java11
-rw-r--r--status.xml4
-rw-r--r--test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java5
-rw-r--r--test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl13
-rw-r--r--test/java/org/apache/fop/accessibility/fo/language.fo30
-rw-r--r--test/java/org/apache/fop/fo/properties/CommonHyphenationTestCase.java58
-rw-r--r--test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml3
-rw-r--r--test/layoutengine/standard-testcases/page-sequence_language.xml12
-rw-r--r--test/pdf/accessibility/language.fo30
-rw-r--r--test/pdf/accessibility/pdf/complete.pdfbin94698 -> 94714 bytes
-rw-r--r--test/pdf/accessibility/pdf/language.pdfbin0 -> 8739 bytes
-rw-r--r--test/pdf/accessibility/pdf/side-regions.pdfbin26963 -> 26943 bytes
-rw-r--r--test/pdf/accessibility/pdf/table_row-col-span.pdfbin18844 -> 18824 bytes
-rw-r--r--test/pdf/accessibility/pdf/text_2.pdfbin10247 -> 10263 bytes
-rw-r--r--test/pdf/accessibility/pdf/th_scope.pdfbin15495 -> 15475 bytes
24 files changed, 281 insertions, 114 deletions
diff --git a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
index 09a814ef5..6a763a6f6 100644
--- a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
+++ b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
@@ -22,7 +22,8 @@ package org.apache.fop.accessibility.fo;
import java.util.Locale;
import java.util.Stack;
-import org.xml.sax.SAXException;
+import javax.xml.XMLConstants;
+
import org.xml.sax.helpers.AttributesImpl;
import org.apache.fop.accessibility.StructureTreeElement;
@@ -59,8 +60,11 @@ import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.LayoutMasterSet;
import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Root;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.fo.properties.CommonAccessibilityHolder;
+import org.apache.fop.fo.properties.CommonHyphenation;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLUtil;
/**
@@ -76,16 +80,20 @@ class StructureTreeEventTrigger extends FOEventHandler {
private final Stack<Boolean> inTableHeader = new Stack<Boolean>();
+ private final Stack<Locale> locales = new Stack<Locale>();
+
public StructureTreeEventTrigger(StructureTreeEventHandler structureTreeEventHandler) {
this.structureTreeEventHandler = structureTreeEventHandler;
}
@Override
- public void startDocument() throws SAXException {
+ public void startRoot(Root root) {
+ locales.push(root.getLocale());
}
@Override
- public void endDocument() throws SAXException {
+ public void endRoot(Root root) {
+ locales.pop();
}
@Override
@@ -93,13 +101,11 @@ class StructureTreeEventTrigger extends FOEventHandler {
if (layoutMasterSet == null) {
layoutMasterSet = pageSeq.getRoot().getLayoutMasterSet();
}
- Locale locale = null;
- if (pageSeq.getLanguage() != null) {
- if (pageSeq.getCountry() != null) {
- locale = new Locale(pageSeq.getLanguage(), pageSeq.getCountry());
- } else {
- locale = new Locale(pageSeq.getLanguage());
- }
+ Locale locale = pageSeq.getLocale();
+ if (locale != null) {
+ locales.push(locale);
+ } else {
+ locales.push(locales.peek());
}
String role = pageSeq.getCommonAccessibility().getRole();
structureTreeEventHandler.startPageSequence(locale, role);
@@ -108,6 +114,7 @@ class StructureTreeEventTrigger extends FOEventHandler {
@Override
public void endPageSequence(PageSequence pageSeq) {
structureTreeEventHandler.endPageSequence();
+ locales.pop();
}
@Override
@@ -171,12 +178,28 @@ class StructureTreeEventTrigger extends FOEventHandler {
@Override
public void startBlock(Block bl) {
- startElement(bl);
+ CommonHyphenation hyphProperties = bl.getCommonHyphenation();
+ AttributesImpl attributes = createLangAttribute(hyphProperties);
+ startElement(bl, attributes);
+ }
+
+ private AttributesImpl createLangAttribute(CommonHyphenation hyphProperties) {
+ Locale locale = hyphProperties.getLocale();
+ AttributesImpl attributes = new AttributesImpl();
+ if (locale == null || locale.equals(locales.peek())) {
+ locales.push(locales.peek());
+ } else {
+ locales.push(locale);
+ addAttribute(attributes, XMLConstants.XML_NS_URI, "lang", "xml",
+ LanguageTags.toLanguageTag(locale));
+ }
+ return attributes;
}
@Override
public void endBlock(Block bl) {
endElement(bl);
+ locales.pop();
}
@Override
@@ -393,8 +416,10 @@ class StructureTreeEventTrigger extends FOEventHandler {
@Override
public void character(Character c) {
- startElementWithID(c);
+ AttributesImpl attributes = createLangAttribute(c.getCommonHyphenation());
+ startElementWithID(c, attributes);
endElement(c);
+ locales.pop();
}
@Override
@@ -409,7 +434,10 @@ class StructureTreeEventTrigger extends FOEventHandler {
}
private void startElementWithID(FONode node) {
- AttributesImpl attributes = new AttributesImpl();
+ startElementWithID(node, new AttributesImpl());
+ }
+
+ private void startElementWithID(FONode node, AttributesImpl attributes) {
String localName = node.getLocalName();
if (node instanceof CommonAccessibilityHolder) {
addRole((CommonAccessibilityHolder) node, attributes);
diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java
index e965d15fc..a606f9727 100644
--- a/src/java/org/apache/fop/area/AreaTreeParser.java
+++ b/src/java/org/apache/fop/area/AreaTreeParser.java
@@ -84,6 +84,7 @@ import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.ConversionUtils;
import org.apache.fop.util.DefaultErrorListener;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLConstants;
import org.apache.fop.util.XMLUtil;
@@ -394,10 +395,10 @@ public class AreaTreeParser {
public void startElement(Attributes attributes) {
PageSequence pageSequence = new PageSequence(null);
- String lang = attributes.getValue("language");
- pageSequence.setLanguage(lang);
- String country = attributes.getValue("country");
- pageSequence.setCountry(country);
+ String lang = attributes.getValue(javax.xml.XMLConstants.XML_NS_URI, "lang");
+ if (lang != null) {
+ pageSequence.setLocale(LanguageTags.toLocale(lang));
+ }
transferForeignObjects(attributes, pageSequence);
areaStack.push(pageSequence);
}
diff --git a/src/java/org/apache/fop/area/PageSequence.java b/src/java/org/apache/fop/area/PageSequence.java
index 1f0411b00..124476602 100644
--- a/src/java/org/apache/fop/area/PageSequence.java
+++ b/src/java/org/apache/fop/area/PageSequence.java
@@ -20,6 +20,7 @@
package org.apache.fop.area;
import java.util.List;
+import java.util.Locale;
/**
* Represents a page sequence in the area tree.
@@ -28,8 +29,8 @@ public class PageSequence extends AreaTreeObject {
private List<PageViewport> pages = new java.util.ArrayList<PageViewport>();
private LineArea title;
- private String language;
- private String country;
+
+ private Locale locale;
/**
* Main constructor
@@ -88,43 +89,21 @@ public class PageSequence extends AreaTreeObject {
}
/**
- * Returns the language of the page-sequence.
- * @return the language (the value of the language property, "none" is mapped to null)
- */
- public String getLanguage() {
- return this.language;
- }
-
- /**
- * Sets the language that applies to this page-sequence.
- * @param language the language to set ("none" is mapped to null)
- */
- public void setLanguage(String language) {
- if ("none".equals(language)) {
- this.language = null;
- } else {
- this.language = language;
- }
- }
-
- /**
- * Returns the country of the page-sequence.
- * @return the country (the value of the country property, "none" is mapped to null)
+ * Sets the locale that applies to this page-sequence.
+ *
+ * @param locale the locale to set
*/
- public String getCountry() {
- return this.country;
+ public void setLocale(Locale locale) {
+ this.locale = locale;
}
/**
- * Sets the country that applies to this page-sequence.
- * @param country the country to set ("none" is mapped to null)
+ * Returns the locale of this page-sequence.
+ *
+ * @return the locale, {@code null} if not set
*/
- public void setCountry(String country) {
- if ("none".equals(country)) {
- this.country = null;
- } else {
- this.country = country;
- }
+ public Locale getLocale() {
+ return locale;
}
}
diff --git a/src/java/org/apache/fop/fo/pagination/PageSequence.java b/src/java/org/apache/fop/fo/pagination/PageSequence.java
index 63114b507..6039dafeb 100644
--- a/src/java/org/apache/fop/fo/pagination/PageSequence.java
+++ b/src/java/org/apache/fop/fo/pagination/PageSequence.java
@@ -19,6 +19,7 @@
package org.apache.fop.fo.pagination;
+import java.util.Locale;
import java.util.Map;
import java.util.Stack;
@@ -30,6 +31,7 @@ import org.apache.fop.datatypes.Numeric;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonHyphenation;
import org.apache.fop.traits.Direction;
import org.apache.fop.traits.WritingMode;
import org.apache.fop.traits.WritingModeTraits;
@@ -41,13 +43,11 @@ import org.apache.fop.traits.WritingModeTraitsGetter;
*/
public class PageSequence extends AbstractPageSequence implements WritingModeTraitsGetter {
- // The value of FO traits (refined properties) that apply to fo:page-sequence.
- private String country;
- private String language;
private String masterReference;
private Numeric referenceOrientation;
private WritingModeTraits writingModeTraits;
- // End of trait values
+
+ private Locale locale;
// There doesn't seem to be anything in the spec requiring flows
// to be in the order given, only that they map to the regions
@@ -90,8 +90,9 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
- country = pList.get(PR_COUNTRY).getString();
- language = pList.get(PR_LANGUAGE).getString();
+ String country = pList.get(PR_COUNTRY).getString();
+ String language = pList.get(PR_LANGUAGE).getString();
+ locale = CommonHyphenation.toLocale(language, country);
masterReference = pList.get(PR_MASTER_REFERENCE).getString();
referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric();
writingModeTraits = new WritingModeTraits
@@ -320,20 +321,8 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra
return FO_PAGE_SEQUENCE;
}
- /**
- * Get the value of the <code>country</code> trait.
- * @return the country trait value
- */
- public String getCountry() {
- return this.country;
- }
-
- /**
- * Get the value of the <code>language</code> trait.
- * @return the language trait value
- */
- public String getLanguage() {
- return this.language;
+ public Locale getLocale() {
+ return locale;
}
/**
diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java
index 1a2ce718b..6db8d6db1 100644
--- a/src/java/org/apache/fop/fo/pagination/Root.java
+++ b/src/java/org/apache/fop/fo/pagination/Root.java
@@ -36,6 +36,7 @@ import org.apache.fop.fo.extensions.destination.Destination;
import org.apache.fop.fo.pagination.bookmarks.BookmarkTree;
import org.apache.fop.fo.properties.CommonAccessibility;
import org.apache.fop.fo.properties.CommonAccessibilityHolder;
+import org.apache.fop.fo.properties.CommonHyphenation;
/**
* Class modeling the <a href="http://www.w3.org/TR/xsl/#fo_root">
@@ -92,17 +93,7 @@ public class Root extends FObj implements CommonAccessibilityHolder {
mediaUsage = pList.get(PR_MEDIA_USAGE).getEnum();
String language = pList.get(PR_LANGUAGE).getString();
String country = pList.get(PR_COUNTRY).getString();
- if (isLocalePropertySet(language)) {
- if (isLocalePropertySet(country)) {
- locale = new Locale(language, country);
- } else {
- locale = new Locale(language);
- }
- }
- }
-
- private boolean isLocalePropertySet(String property) {
- return property != null && !property.equals("none");
+ locale = CommonHyphenation.toLocale(language, country);
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
index 8394a4b18..d5f4c538b 100644
--- a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
+++ b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
@@ -19,6 +19,8 @@
package org.apache.fop.fo.properties;
+import java.util.Locale;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -185,6 +187,41 @@ public final class CommonHyphenation {
return font.getCharWidth(hyphChar);
}
+ /**
+ * Creates and returns a {@link Locale} representation of the language and country.
+ *
+ * @return the language (and the country if set) represented as a locale, {@code null}
+ * if the language has not been set (i.e., has been left to its initial value of
+ * "none")
+ */
+ public Locale getLocale() {
+ return toLocale(language.getString(), country.getString());
+ }
+
+ /**
+ * Creates and returns a {@link Locale} representation of the given language, and the
+ * given country if set. The country is considered to be set if not {@code null} and
+ * not set to "none".
+ *
+ * @return the language and country represented as a locale, {@code null} if the
+ * language is null or "none" (case insensitive)
+ */
+ public static Locale toLocale(String language, String country) {
+ Locale locale = null;
+ if (isDefined(language)) {
+ if (isDefined(country)) {
+ locale = new Locale(language, country);
+ } else {
+ locale = new Locale(language);
+ }
+ }
+ return locale;
+ }
+
+ private static boolean isDefined(String property) {
+ return !(property == null || property.equalsIgnoreCase("none"));
+ }
+
/** {@inheritDoc} */
public boolean equals(Object obj) {
if (obj == this) {
diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
index 43f231cf3..577f172eb 100644
--- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
@@ -99,8 +99,7 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager
org.apache.fop.area.PageSequence pageSequenceAreaObject
= new org.apache.fop.area.PageSequence(title);
transferExtensions(pageSequenceAreaObject);
- pageSequenceAreaObject.setLanguage(getPageSequence().getLanguage());
- pageSequenceAreaObject.setCountry(getPageSequence().getCountry());
+ pageSequenceAreaObject.setLocale(getPageSequence().getLocale());
areaTreeModel.startPageSequence(pageSequenceAreaObject);
if (log.isDebugEnabled()) {
log.debug("Starting layout");
diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
index 57f13ac07..771929809 100644
--- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
@@ -520,7 +520,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
this.inPageSequence = true;
}
establishForeignAttributes(pageSequence.getForeignAttributes());
- documentHandler.getContext().setLanguage(toLocale(pageSequence));
+ documentHandler.getContext().setLanguage(pageSequence.getLocale());
documentHandler.startPageSequence(null);
resetForeignAttributes();
processExtensionAttachments(pageSequence);
@@ -529,17 +529,6 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
}
}
- private Locale toLocale(PageSequence pageSequence) {
- if (pageSequence.getLanguage() != null) {
- if (pageSequence.getCountry() != null) {
- return new Locale(pageSequence.getLanguage(), pageSequence.getCountry());
- } else {
- return new Locale(pageSequence.getLanguage());
- }
- }
- return null;
- }
-
private Metadata createDefaultDocumentMetadata() {
Metadata xmp = new Metadata();
DublinCoreAdapter dc = DublinCoreSchema.getAdapter(xmp);
diff --git a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
index 031224ffb..08aad08f6 100644
--- a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
+++ b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
@@ -23,6 +23,8 @@ import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
+import javax.xml.XMLConstants;
+
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
@@ -42,6 +44,7 @@ import org.apache.fop.pdf.StandardStructureTypes.Grouping;
import org.apache.fop.pdf.StandardStructureTypes.Table;
import org.apache.fop.pdf.StructureHierarchyMember;
import org.apache.fop.pdf.StructureType;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLUtil;
class PDFStructureTreeBuilder implements StructureTreeEventHandler {
@@ -62,10 +65,10 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
addBuilder("static-content", regionBuilder);
addBuilder("flow", regionBuilder);
// Block-level Formatting Objects
- addBuilder("block", StandardStructureTypes.Paragraphlike.P);
+ addBuilder("block", new LanguageHolderBuilder(StandardStructureTypes.Paragraphlike.P));
addBuilder("block-container", StandardStructureTypes.Grouping.DIV);
// Inline-level Formatting Objects
- addBuilder("character", StandardStructureTypes.InlineLevelStructure.SPAN);
+ addBuilder("character", new LanguageHolderBuilder(StandardStructureTypes.InlineLevelStructure.SPAN));
addBuilder("external-graphic", new ImageBuilder());
addBuilder("instream-foreign-object", new ImageBuilder());
addBuilder("inline", StandardStructureTypes.InlineLevelStructure.SPAN);
@@ -192,6 +195,23 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
}
+ private static class LanguageHolderBuilder extends DefaultStructureElementBuilder {
+
+ LanguageHolderBuilder(StructureType structureType) {
+ super(structureType);
+ }
+
+ @Override
+ protected void setAttributes(PDFStructElem structElem, Attributes attributes) {
+ String xmlLang = attributes.getValue(XMLConstants.XML_NS_URI, "lang");
+ if (xmlLang != null) {
+ Locale locale = LanguageTags.toLocale(xmlLang);
+ structElem.setLanguage(locale);
+ }
+ }
+
+ }
+
private static class ImageBuilder extends DefaultStructureElementBuilder {
ImageBuilder() {
diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java
index cf3cbe5a2..4a920d18d 100644
--- a/src/java/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java
@@ -27,8 +27,10 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import javax.xml.XMLConstants;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
@@ -86,6 +88,7 @@ import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.XMLHandler;
import org.apache.fop.util.ColorUtil;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLUtil;
/**
@@ -450,11 +453,9 @@ public class XMLRenderer extends AbstractXMLRenderer {
endPageSequence(); // move this before handleDocumentExtensionAttachments() ?
startedSequence = true;
atts.clear();
- if (pageSequence.getLanguage() != null) {
- addAttribute("language", pageSequence.getLanguage());
- }
- if (pageSequence.getCountry() != null) {
- addAttribute("country", pageSequence.getCountry());
+ Locale locale = pageSequence.getLocale();
+ if (locale != null) {
+ addAttribute(new QName(XMLConstants.XML_NS_URI, "xml:lang"), LanguageTags.toLanguageTag(locale));
}
transferForeignObjects(pageSequence);
startElement("pageSequence", atts);
diff --git a/status.xml b/status.xml
index 76b25a9eb..78cf4efc2 100644
--- a/status.xml
+++ b/status.xml
@@ -62,6 +62,10 @@
documents. Example: the fix of marks layering will be such a case when it's done.
-->
<release version="FOP Trunk" date="TBD">
+ <action context="Renderers" dev="VH" type="add" fixes-bug="53980">
+ PDF accessibility: Store language information coming from fo:block or fo:character in the
+ structure tree.
+ </action>
<action context="Layout" dev="MH" type="add" fixes-bug="53924" due-to="Luis Bernardo">
Support for retrieve-table-markers
</action>
diff --git a/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java b/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
index 87b970576..a86b5b2b2 100644
--- a/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
+++ b/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
@@ -96,6 +96,11 @@ public class FO2StructureTreeConverterTestCase {
testConverter("table-header_scope.fo");
}
+ @Test
+ public void testLanguage() throws Exception {
+ testConverter("language.fo");
+ }
+
private static InputStream getResource(String name) {
return FO2StructureTreeConverterTestCase.class.getResourceAsStream(name);
}
diff --git a/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl b/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl
index 90d74a7c4..a9de38db1 100644
--- a/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl
+++ b/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl
@@ -150,11 +150,22 @@
<xsl:template match="fo:leader"/>
- <!-- Keep fox:alt-text and role attributes, discard everything else -->
+ <!-- Keep the relevant attributes, discard everything else -->
<xsl:template match="@fox:alt-text|@role">
<xsl:copy-of select="."/>
</xsl:template>
+ <xsl:template match="fo:block/@language[. != ../ancestor::*[@language][1]/@language]
+ |fo:character/@language[. != ../ancestor::*[@language][1]/@language]">
+ <xsl:attribute name="xml:lang">
+ <xsl:value-of select="."/>
+ <xsl:if test="../@country[. != 'none']">
+ <xsl:text>-</xsl:text>
+ <xsl:value-of select="../@country"/>
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:template>
+
<xsl:template match="@*"/>
diff --git a/test/java/org/apache/fop/accessibility/fo/language.fo b/test/java/org/apache/fop/accessibility/fo/language.fo
new file mode 100644
index 000000000..8dfb2694a
--- /dev/null
+++ b/test/java/org/apache/fop/accessibility/fo/language.fo
@@ -0,0 +1,30 @@
+<?xml version="1.0" standalone="no"?>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
+ font-family="sans-serif">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="170pt" page-width="220pt" margin="10pt">
+ <fo:region-body display-align="center"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:flow flow-name="xsl-region-body" line-height="10pt" font-size="8pt" space-before="5pt"
+ space-after="5pt">
+ <fo:block>This block of text is written in the default language of the page sequence, which is
+ British English.</fo:block>
+ <fo:block language="fr" country="FR" space-before="inherit" space-after="inherit">Ce text est
+ écrit dans une autre langue, en l’occurence le français de France.
+ <fo:block language="en" country="US" space-before="inherit" start-indent="1em"
+ space-after="inherit">However, this block of French text encloses a block of American
+ English.
+ <fo:block space-before="inherit" start-indent="2em" space-after="inherit" language="en"
+ country="US">The structure element corresponding to this block should have no language
+ set as it is the same as on the parent block.</fo:block></fo:block>
+ Maintenant on revient au français.</fo:block>
+ <fo:block space-before="inherit">And now we are back to the English language, with a
+ <fo:character character="F" language="fr" country="none" color="blue"/>rench
+ character.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
diff --git a/test/java/org/apache/fop/fo/properties/CommonHyphenationTestCase.java b/test/java/org/apache/fop/fo/properties/CommonHyphenationTestCase.java
new file mode 100644
index 000000000..029146413
--- /dev/null
+++ b/test/java/org/apache/fop/fo/properties/CommonHyphenationTestCase.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo.properties;
+
+import java.util.Locale;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class CommonHyphenationTestCase {
+
+ private final String lang = "en";
+
+ @Test
+ public void testToLocaleNull() {
+ Locale locale = CommonHyphenation.toLocale(null, null);
+ assertNull(locale);
+ locale = CommonHyphenation.toLocale("none", null);
+ assertNull(locale);
+ locale = CommonHyphenation.toLocale("NoNe", "US");
+ assertNull(locale);
+ }
+
+ @Test
+ public void testToLocaleWithJustLanguage() {
+ Locale locale = new Locale(lang);
+ assertEquals(locale, CommonHyphenation.toLocale(lang, null));
+ assertEquals(locale, CommonHyphenation.toLocale(lang, "none"));
+ assertEquals(locale, CommonHyphenation.toLocale(lang, "NONE"));
+ }
+
+ @Test
+ public void testToLocaleWithLanguageAndCountry() {
+ Locale locale = new Locale(lang, "US");
+ assertEquals(locale, CommonHyphenation.toLocale(lang, "US"));
+ assertEquals(locale, CommonHyphenation.toLocale(lang, "us"));
+ }
+
+}
diff --git a/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml b/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml
index 084f1e685..9f94969cb 100644
--- a/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml
+++ b/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml
@@ -45,8 +45,7 @@
</fo>
<checks>
<eval expected="1" xpath="count(//pageViewport)"/>
- <eval expected="en" xpath="/areaTree/pageSequence/@language"/>
- <true xpath="not(boolean(/areaTree/pageSequence/@country))"/>
+ <eval expected="en" xpath="/areaTree/pageSequence/@xml:lang"/>
<eval expected="17230" xpath="//flow/block[1]/lineArea[1]/text[1]/@twsadjust"/>
<eval expected="-1339" xpath="//flow/block[1]/lineArea[2]/text[1]/@twsadjust"/>
diff --git a/test/layoutengine/standard-testcases/page-sequence_language.xml b/test/layoutengine/standard-testcases/page-sequence_language.xml
index f2fa610bc..4ff0fe3b3 100644
--- a/test/layoutengine/standard-testcases/page-sequence_language.xml
+++ b/test/layoutengine/standard-testcases/page-sequence_language.xml
@@ -53,17 +53,13 @@
</fo:root>
</fo>
<checks>
- <eval expected="en" xpath="/areaTree/pageSequence[1]/@language"/>
- <true xpath="not(boolean(/areaTree/pageSequence[1]/@country))"/>
+ <eval expected="en" xpath="/areaTree/pageSequence[1]/@xml:lang"/>
- <eval expected="en" xpath="/areaTree/pageSequence[2]/@language"/>
- <eval expected="US" xpath="/areaTree/pageSequence[2]/@country"/>
+ <eval expected="en-US" xpath="/areaTree/pageSequence[2]/@xml:lang"/>
- <eval expected="de" xpath="/areaTree/pageSequence[3]/@language"/>
- <eval expected="CH" xpath="/areaTree/pageSequence[3]/@country"/>
+ <eval expected="de-CH" xpath="/areaTree/pageSequence[3]/@xml:lang"/>
- <eval expected="de" xpath="/areaTree/pageSequence[4]/@language"/>
- <true xpath="not(boolean(/areaTree/pageSequence[4]/@country))"/>
+ <eval expected="de" xpath="/areaTree/pageSequence[4]/@xml:lang"/>
</checks>
<if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate">
<eval expected="en" xpath="//if:page-sequence[1]/@xml:lang"/>
diff --git a/test/pdf/accessibility/language.fo b/test/pdf/accessibility/language.fo
new file mode 100644
index 000000000..8dfb2694a
--- /dev/null
+++ b/test/pdf/accessibility/language.fo
@@ -0,0 +1,30 @@
+<?xml version="1.0" standalone="no"?>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
+ font-family="sans-serif">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="170pt" page-width="220pt" margin="10pt">
+ <fo:region-body display-align="center"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:flow flow-name="xsl-region-body" line-height="10pt" font-size="8pt" space-before="5pt"
+ space-after="5pt">
+ <fo:block>This block of text is written in the default language of the page sequence, which is
+ British English.</fo:block>
+ <fo:block language="fr" country="FR" space-before="inherit" space-after="inherit">Ce text est
+ écrit dans une autre langue, en l’occurence le français de France.
+ <fo:block language="en" country="US" space-before="inherit" start-indent="1em"
+ space-after="inherit">However, this block of French text encloses a block of American
+ English.
+ <fo:block space-before="inherit" start-indent="2em" space-after="inherit" language="en"
+ country="US">The structure element corresponding to this block should have no language
+ set as it is the same as on the parent block.</fo:block></fo:block>
+ Maintenant on revient au français.</fo:block>
+ <fo:block space-before="inherit">And now we are back to the English language, with a
+ <fo:character character="F" language="fr" country="none" color="blue"/>rench
+ character.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/pdf/complete.pdf b/test/pdf/accessibility/pdf/complete.pdf
index a9bb3df77..38d9bc499 100644
--- a/test/pdf/accessibility/pdf/complete.pdf
+++ b/test/pdf/accessibility/pdf/complete.pdf
Binary files differ
diff --git a/test/pdf/accessibility/pdf/language.pdf b/test/pdf/accessibility/pdf/language.pdf
new file mode 100644
index 000000000..ee4cd0b2d
--- /dev/null
+++ b/test/pdf/accessibility/pdf/language.pdf
Binary files differ
diff --git a/test/pdf/accessibility/pdf/side-regions.pdf b/test/pdf/accessibility/pdf/side-regions.pdf
index 6e5da9393..1bd64e115 100644
--- a/test/pdf/accessibility/pdf/side-regions.pdf
+++ b/test/pdf/accessibility/pdf/side-regions.pdf
Binary files differ
diff --git a/test/pdf/accessibility/pdf/table_row-col-span.pdf b/test/pdf/accessibility/pdf/table_row-col-span.pdf
index 65921fe5a..603717d2e 100644
--- a/test/pdf/accessibility/pdf/table_row-col-span.pdf
+++ b/test/pdf/accessibility/pdf/table_row-col-span.pdf
Binary files differ
diff --git a/test/pdf/accessibility/pdf/text_2.pdf b/test/pdf/accessibility/pdf/text_2.pdf
index 0283764cd..4411b302f 100644
--- a/test/pdf/accessibility/pdf/text_2.pdf
+++ b/test/pdf/accessibility/pdf/text_2.pdf
Binary files differ
diff --git a/test/pdf/accessibility/pdf/th_scope.pdf b/test/pdf/accessibility/pdf/th_scope.pdf
index 596ffb7db..27159520b 100644
--- a/test/pdf/accessibility/pdf/th_scope.pdf
+++ b/test/pdf/accessibility/pdf/th_scope.pdf
Binary files differ