none
How to change OpenXML Word Document Language (Culture Info) RRS feed

  • Question

  • Hi,

    I am working on Microsoft Word Reporting (OpenXML 2.0). The company we developing this report for has its clients all over the world and due to of its universal usage and access, One of the requirements are to provide multi language support.

    Let's suppose my CurrentCulture is "en-GB" while CurrentUICulture is "en-US". I am fetching report data from DB and when I lay down this data in word report, It automatically converts it into "en-GB" which is the CurrentCulture of my local machine. Now could please anyone tell me how I can change the language from "en-GB" to any other language (e.g "en-US", "en-CA") through OpenXML C#.

    I have tried the approach which is discussed here but ending up with "en-GB" all the times.

    Kind Regards!

    Monday, August 6, 2012 9:00 AM

Answers

  • Hello waseem327,

    Welcome to Open XML Forma SDK Forum.

    Open XML SDK 2.x doesn't attach any locale or culture information implicitly to a generated/modified Office document by detecting the culture of the thread.

    <w:lang> tags in styles.xml, stylesWithEffects.xml, document.xml
    http://msdn.microsoft.com/ja-jp/library/documentformat.openxml.wordprocessing.languages.aspx

    <w:activeWritingStyle> tag in settings.xm
    lhttp://msdn.microsoft.com/ja-jp/library/documentformat.openxml.wordprocessing.activewritingstyle.aspx

    To change the language, culture infomation written in those two types of tags have to be modified. If either of the two types of the tags are not exisitent in your documents,  <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/> should be inserted in <w:docDefaults> section of styles.xml as a default run property. I suppose the reason why the document culture is fixed to"en-GB" is either of;

    1. the generated document contains w:val="en-GB" tags.
    2. the generated document none of language tags, and "en-GB" is chosen by Word application in accordance with the local Office settings.

    Best Regards,
    Kazunori


    Monday, August 6, 2012 10:51 AM
  • Hi Waseem,

    Let's see whether following snippet can help you:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Wordprocessing;
    using log4net;
    using System.Windows.Forms;
    using DocumentFormat.OpenXml;
    
    namespace CultureOpenXml
    {
        class Program
        {
            [STAThread]
            static void Main(string[] args)
            {
                ILog log = log4net.LogManager.GetLogger(typeof(Program));
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Filter = "Word document |*.docx";
                sfd.ShowDialog();
                using (WordprocessingDocument objWordDocument = 
                    WordprocessingDocument.Create(sfd.FileName, 
                    WordprocessingDocumentType.Document))
                {
                    MainDocumentPart objMainDocumentPart = 
                        objWordDocument.AddMainDocumentPart();
                    Document objDocument = new Document();
                    Body objBody = new Body();
                    Paragraph p = new Paragraph();
                    ParagraphProperties pp = new ParagraphProperties();
                    Justification j = new Justification()
                    {
                        Val = JustificationValues.Right
                    };
                    pp.Append(j);
                    p.Append(pp);
                    Run r = new Run();
                    Text t = new Text();
                    RunProperties rp = new RunProperties();
                    Languages l = new Languages();
                    l.Val = "he-IL";
                    l.Bidi = "he-IL";
                    rp.Append(l);
                    t.Text = "משה את עשרת הדברות";
                    r.Append(rp);
                    r.Append(t);
                    p.Append(r);
                    objBody.Append(p);
                    objDocument.Append(objBody);
                    objMainDocumentPart.Document = objDocument;
                    DocumentSettingsPart objDocumentSettingPart = 
                        objMainDocumentPart.AddNewPart<DocumentSettingsPart>();
                    objDocumentSettingPart.Settings = new Settings();
                    Compatibility objCompatibility = new Compatibility();
                    CompatibilitySetting objCompatibilitySetting =
                        new CompatibilitySetting()
                        {
                            Name = CompatSettingNameValues.CompatibilityMode,
                            Uri = "http://schemas.microsoft.com/office/word",
                            Val = "14"
                        };
                    objCompatibility.Append(objCompatibilitySetting);
                    ActiveWritingStyle aws = new ActiveWritingStyle()
                    {
                        Language = "he-IL"
                    };
                    objDocumentSettingPart.Settings.Append(objCompatibility);
                    objDocumentSettingPart.Settings.Append(aws);
                }
            }
        }
    }

    T.X.

    志异征诛,三让两家王朝
    功同开辟,一桮万古江南

    Thursday, August 9, 2012 12:38 PM
  • Here is sample code to modify language settings in;

    1. Styles
    2. StylesWithEffect
    3. ThemeFont
    4. ActiveWriting Style

    #1 and #2 are mandatory. #3 and #4 are optional. This sample may not affect calendar, ruby, and kinsoku.

    using System;
    using System.Text;
    using System.IO;
    using System.Collections.Generic;
    using System.Linq;
    using System.Xml;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml;
    using DocumentFormat.OpenXml.Wordprocessing;
    namespace OOXMLSDKHELP
    {
    class Program
    {
    static void Main(string[] args)
    {
    	string target_lang = "en-GB";
    	string target_latin_lang = "en-GB";
    	string target_ea_lang = "en-GB";
    	string target_bidi_lang = "en-GB";
    	Languages target_languages = new Languages() 
    	{ Val = target_latin_lang, EastAsia = target_ea_lang, Bidi = target_bidi_lang };
    	Languages target_se_languages = new Languages() 
    	{ Val = target_latin_lang, EastAsia = target_ea_lang, Bidi = target_bidi_lang };
    	ThemeFontLanguages target_theme_languages = new ThemeFontLanguages
    	{ Val = target_latin_lang, EastAsia = target_ea_lang, Bidi = target_bidi_lang };
    	string target_writestyle_lang = target_lang;
    	using (WordprocessingDocument doc = WordprocessingDocument.Open("sample.docx",true))
    	{
    	StyleDefinitionsPart stylePart = doc.MainDocumentPart.StyleDefinitionsPart;
    	if (stylePart != null)
    	{
    		DocDefaults docStyleDefaults = stylePart.Styles.DocDefaults;
    		if (docStyleDefaults != null)
    		{
    			if (docStyleDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Languages == null)
    				docStyleDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Append(new Languages());
    			docStyleDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Languages = target_languages;
    			stylePart.Styles.Save();
    		}
    		else wrong("This sample does not support cases where <w:docDefaults> is inexistent.");
    	}
    	StylesWithEffectsPart styleEffectPart = doc.MainDocumentPart.StylesWithEffectsPart;
    	if (styleEffectPart != null)
    	{
    		DocDefaults docStyleEffectDefaults = styleEffectPart.Styles.DocDefaults;
    		if (docStyleEffectDefaults != null)
    		{
    		    if (docStyleEffectDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Languages == null)
    				docStyleEffectDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Append(new Languages());
    			docStyleEffectDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Languages = target_se_languages;
    			styleEffectPart.Styles.Save();
    		}
    	}
    	// This section is optional. In many cases, setting languages in styles is sufficient. 
    	DocumentSettingsPart docSettingPart = doc.MainDocumentPart.DocumentSettingsPart;
    	if (docSettingPart != null)
    	{
    		foreach (ThemeFontLanguages themeFontLanguages in docSettingPart.Settings.Elements<ThemeFontLanguages>())
    			themeFontLanguages.Remove();
    		docSettingPart.Settings.Append(target_theme_languages);
    		// if the settings already have the proper ActiveWritingStyle, this must not be removed...
    		bool lang_match = false;
    		foreach (ActiveWritingStyle activeWriteStyle in docSettingPart.Settings.Elements<ActiveWritingStyle>())
    		{
    			if (activeWriteStyle.Language != target_writestyle_lang) activeWriteStyle.Remove();
    				else lang_match = true;
    		}
    		if (!lang_match) docSettingPart.Settings.Append(new ActiveWritingStyle() { Language = target_writestyle_lang });
    		docSettingPart.Settings.Save();
    	}
        }
    }
    public static void wrong(string msg)
    {
    	Console.WriteLine(msg);
    	Console.ReadLine();
    	Environment.Exit(0);
    }
    }
    }
    Friday, August 10, 2012 8:12 AM

All replies

  • Hello waseem327,

    Welcome to Open XML Forma SDK Forum.

    Open XML SDK 2.x doesn't attach any locale or culture information implicitly to a generated/modified Office document by detecting the culture of the thread.

    <w:lang> tags in styles.xml, stylesWithEffects.xml, document.xml
    http://msdn.microsoft.com/ja-jp/library/documentformat.openxml.wordprocessing.languages.aspx

    <w:activeWritingStyle> tag in settings.xm
    lhttp://msdn.microsoft.com/ja-jp/library/documentformat.openxml.wordprocessing.activewritingstyle.aspx

    To change the language, culture infomation written in those two types of tags have to be modified. If either of the two types of the tags are not exisitent in your documents,  <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/> should be inserted in <w:docDefaults> section of styles.xml as a default run property. I suppose the reason why the document culture is fixed to"en-GB" is either of;

    1. the generated document contains w:val="en-GB" tags.
    2. the generated document none of language tags, and "en-GB" is chosen by Word application in accordance with the local Office settings.

    Best Regards,
    Kazunori


    Monday, August 6, 2012 10:51 AM
  • Hello Kazunori Matsuura,

    Thank you very much for your quick reply!

    You are right I can see "en-GB" (     <w:lang w:val="en-GB" w:bidi="ar-SA" w:eastAsia="en-US"/>) in styles.xml, but there is no <w:activeWritingStyle> tag in settings.xml.

    Can you please give me some code sample (C#), how to do the modification ?

    I tried by accessing the StyleDefinitionPart of my document but unsuccessful.

    Kind Regards,

    Waseem


    • Edited by waseem327 Monday, August 6, 2012 11:40 AM
    Monday, August 6, 2012 11:39 AM
  • Okay, let me try writing the sample. Please stay tuned.

    Thanks,
    Kazunori


    Tuesday, August 7, 2012 2:14 PM
  • Hi Waseem,

    Let's see whether following snippet can help you:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Wordprocessing;
    using log4net;
    using System.Windows.Forms;
    using DocumentFormat.OpenXml;
    
    namespace CultureOpenXml
    {
        class Program
        {
            [STAThread]
            static void Main(string[] args)
            {
                ILog log = log4net.LogManager.GetLogger(typeof(Program));
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Filter = "Word document |*.docx";
                sfd.ShowDialog();
                using (WordprocessingDocument objWordDocument = 
                    WordprocessingDocument.Create(sfd.FileName, 
                    WordprocessingDocumentType.Document))
                {
                    MainDocumentPart objMainDocumentPart = 
                        objWordDocument.AddMainDocumentPart();
                    Document objDocument = new Document();
                    Body objBody = new Body();
                    Paragraph p = new Paragraph();
                    ParagraphProperties pp = new ParagraphProperties();
                    Justification j = new Justification()
                    {
                        Val = JustificationValues.Right
                    };
                    pp.Append(j);
                    p.Append(pp);
                    Run r = new Run();
                    Text t = new Text();
                    RunProperties rp = new RunProperties();
                    Languages l = new Languages();
                    l.Val = "he-IL";
                    l.Bidi = "he-IL";
                    rp.Append(l);
                    t.Text = "משה את עשרת הדברות";
                    r.Append(rp);
                    r.Append(t);
                    p.Append(r);
                    objBody.Append(p);
                    objDocument.Append(objBody);
                    objMainDocumentPart.Document = objDocument;
                    DocumentSettingsPart objDocumentSettingPart = 
                        objMainDocumentPart.AddNewPart<DocumentSettingsPart>();
                    objDocumentSettingPart.Settings = new Settings();
                    Compatibility objCompatibility = new Compatibility();
                    CompatibilitySetting objCompatibilitySetting =
                        new CompatibilitySetting()
                        {
                            Name = CompatSettingNameValues.CompatibilityMode,
                            Uri = "http://schemas.microsoft.com/office/word",
                            Val = "14"
                        };
                    objCompatibility.Append(objCompatibilitySetting);
                    ActiveWritingStyle aws = new ActiveWritingStyle()
                    {
                        Language = "he-IL"
                    };
                    objDocumentSettingPart.Settings.Append(objCompatibility);
                    objDocumentSettingPart.Settings.Append(aws);
                }
            }
        }
    }

    T.X.

    志异征诛,三让两家王朝
    功同开辟,一桮万古江南

    Thursday, August 9, 2012 12:38 PM
  • Here is sample code to modify language settings in;

    1. Styles
    2. StylesWithEffect
    3. ThemeFont
    4. ActiveWriting Style

    #1 and #2 are mandatory. #3 and #4 are optional. This sample may not affect calendar, ruby, and kinsoku.

    using System;
    using System.Text;
    using System.IO;
    using System.Collections.Generic;
    using System.Linq;
    using System.Xml;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml;
    using DocumentFormat.OpenXml.Wordprocessing;
    namespace OOXMLSDKHELP
    {
    class Program
    {
    static void Main(string[] args)
    {
    	string target_lang = "en-GB";
    	string target_latin_lang = "en-GB";
    	string target_ea_lang = "en-GB";
    	string target_bidi_lang = "en-GB";
    	Languages target_languages = new Languages() 
    	{ Val = target_latin_lang, EastAsia = target_ea_lang, Bidi = target_bidi_lang };
    	Languages target_se_languages = new Languages() 
    	{ Val = target_latin_lang, EastAsia = target_ea_lang, Bidi = target_bidi_lang };
    	ThemeFontLanguages target_theme_languages = new ThemeFontLanguages
    	{ Val = target_latin_lang, EastAsia = target_ea_lang, Bidi = target_bidi_lang };
    	string target_writestyle_lang = target_lang;
    	using (WordprocessingDocument doc = WordprocessingDocument.Open("sample.docx",true))
    	{
    	StyleDefinitionsPart stylePart = doc.MainDocumentPart.StyleDefinitionsPart;
    	if (stylePart != null)
    	{
    		DocDefaults docStyleDefaults = stylePart.Styles.DocDefaults;
    		if (docStyleDefaults != null)
    		{
    			if (docStyleDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Languages == null)
    				docStyleDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Append(new Languages());
    			docStyleDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Languages = target_languages;
    			stylePart.Styles.Save();
    		}
    		else wrong("This sample does not support cases where <w:docDefaults> is inexistent.");
    	}
    	StylesWithEffectsPart styleEffectPart = doc.MainDocumentPart.StylesWithEffectsPart;
    	if (styleEffectPart != null)
    	{
    		DocDefaults docStyleEffectDefaults = styleEffectPart.Styles.DocDefaults;
    		if (docStyleEffectDefaults != null)
    		{
    		    if (docStyleEffectDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Languages == null)
    				docStyleEffectDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Append(new Languages());
    			docStyleEffectDefaults.RunPropertiesDefault.RunPropertiesBaseStyle.Languages = target_se_languages;
    			styleEffectPart.Styles.Save();
    		}
    	}
    	// This section is optional. In many cases, setting languages in styles is sufficient. 
    	DocumentSettingsPart docSettingPart = doc.MainDocumentPart.DocumentSettingsPart;
    	if (docSettingPart != null)
    	{
    		foreach (ThemeFontLanguages themeFontLanguages in docSettingPart.Settings.Elements<ThemeFontLanguages>())
    			themeFontLanguages.Remove();
    		docSettingPart.Settings.Append(target_theme_languages);
    		// if the settings already have the proper ActiveWritingStyle, this must not be removed...
    		bool lang_match = false;
    		foreach (ActiveWritingStyle activeWriteStyle in docSettingPart.Settings.Elements<ActiveWritingStyle>())
    		{
    			if (activeWriteStyle.Language != target_writestyle_lang) activeWriteStyle.Remove();
    				else lang_match = true;
    		}
    		if (!lang_match) docSettingPart.Settings.Append(new ActiveWritingStyle() { Language = target_writestyle_lang });
    		docSettingPart.Settings.Save();
    	}
        }
    }
    public static void wrong(string msg)
    {
    	Console.WriteLine(msg);
    	Console.ReadLine();
    	Environment.Exit(0);
    }
    }
    }
    Friday, August 10, 2012 8:12 AM