Localization in Xamarin Pdf Viewer (SfPdfViewer)

21 Feb 202416 minutes to read

Localization is the process of configuring the application to a specific language. PdfViewerControl supports to localize its static text. SfPdfViewer uses the following static text that can be localized in application level:

Keyword Text(English)
SfPdfViewerCancel Cancel
SfPdfViewerCopy Copy
SfPdfViewerHighlight Highlight
SfPdfViewerHyperlinkCancel Cancel
SfPdfViewerHyperlinkMessage Do you want to open the webpage
SfPdfViewerHyperlinkMessageTitle Open web page
SfPdfViewerHyperlinkOpen Open
SfPdfViewerInvalidPageMessage Invalid Page Number
SfPdfViewerInvalidPageMessageTitle Error
SfPdfViewerNoMatches No matches were found
SfPdfViewerNoOccurrences No more matches were found
SfPdfViewerOkMessage Ok
SfPdfViewerPageEntryCancel Cancel
SfPdfViewerPageEntryOkay Ok
SfPdfViewerPageNumberEntryMessage Enter Page Number
SfPdfViewerPageNumberEntryMessageTitle Go To Page
SfPdfViewerPlaceHolderText Type your text
SfPdfViewerRedo Redo
SfPdfViewerSave Save
SfPdfViewerSearchResult Search Result
SfPdfViewerStrikethrough Strikethrough
SfPdfViewerUnderline Underline
SfPdfViewerUndo Undo
SfPdfViewerSignaturePadTitle Create Signature
SfPdfViewerDone Done
SfPdfViewerClear Clear
SfPdfViewerSignatureCancel Cancel
SfPdfViewerSearchPlaceHolderText Enter text to search
SfPdfViewerBookmarkToolbarTitle Bookmarks
SfPdfViewerNoBookmarksText No Bookmarks
SfPdfViewerPrint Print
SfPdfViewerContinuousPage Continuous Pages
SfPdfViewerPageByPage Page By Page
SfPdfViewerOfMessage Of
SfPdfViewerSubmit Submit
SfPdfViewer_PageNavigationDialog_OfPages of pages
SfPdfViewerPageNumberEntryMessageTitleMaterial Go to Page
SfPdfViewerBookmarkToolbarTitleMaterial Bookmark
SfPdfViewerSignaturePadTitleMaterial Create Signature
SfPdfViewerDoneMaterial DONE
SfPdfViewerClearMaterial CLEAR
SfPdfViewerSubmitMaterial SUBMIT
SfPdfViewerCancelMaterial CANCEL
SfPdfViewerPrintAlertErrorTitle Error
SfPdfViewerPrintAlertErrorMessage Password protected document cannot be printed.
SfPdfViewerClose Close
SfPdfViewerSquiggly Squiggly
SfPdfViewerApply Apply
SfPdfViewerNoBookmarksText No Bookmarks
SfPdfViewerEditLabelHeaderText Rename
SfPdfViewerLoadingBookmarksText Loading....
SfPdfViewerOkButton OK
SfPdfViewerCancelButton Cancel
SfPdfViewerPasswordDialogerrorMessage Invalid Password!
SfPdfViewerPasswordDialogTitle Enter Password
SfPdfViewerPasswordDialogMessage Enter the password to open this PDF File.
SfPdfViewerPasswordDialogPlaceholderText Password
SfPdfViewerXFAErrorAlertTitle XFA Forms PDF
SfPdfViewerXFAErrorAlertMessage The PDF contains XFA Forms which cannot be viewed in PDF Viewer.
SfPdfViewerUnhandledConditionErrorAlertTitle Error loading PDF
SfPdfViewerUnhandledConditionErrorAlertMessage There was an error in loading the PDF
Sfpdfviewer_hinttext Double Tap to activate
Sfpdfviewer_signaturebutton Signature
Sfpdfviewer_textmarkupsbutton Text mark-ups
Sfpdfviewer_inkbutton Ink
Sfpdfviewer_freetextbutton Text
Sfpdfviewer_shapesbutton Shapes
Sfpdfviewer_annotationsbackbutton Annotations Back
Sfpdfviewer_fontsizebutton Font Size
Sfpdfviewer_textbackbutton Text Back
Sfpdfviewer_inkbackbutton Ink Back
Sfpdfviewer_thicknessbutton Thickness
Sfpdfviewer_colorbutton Color
Sfpdfviewer_nextlevelbookmarksbutton Next level bookmarks
Sfpdfviewer_previouslevelbookmarksbutton Previous level bookmarks
Sfpdfviewer_bookmarksbackbutton Bookmarks Back
Sfpdfviewer_annotationsbutton Annotations
Sfpdfviewer_opacitybutton Opacity
Sfpdfviewer_cyancolorbutton Cyan
Sfpdfviewer_magentacolorbutton Magenta
Sfpdfviewer_blackcolorbutton Black
Sfpdfviewer_redcolorbutton Red
Sfpdfviewer_greencolorbutton Green
Sfpdfviewer_yellowcolorbutton Yellow
Sfpdfviewer_deletebutton Delete
Sfpdfviewer_undobutton Undo
Sfpdfviewer_continuouspagebutton Continuous Page
Sfpdfviewer_singlepagebutton Single Page
Sfpdfviewer_redobutton Redo
Sfpdfviewer_savebutton Save
Sfpdfviewer_printbutton Print
Sfpdfviewer_searchnextbutton Search Next
Sfpdfviewer_searchpreviousbutton Search Previous
Sfpdfviewer_cancelsearchbutton Cancel Search
Sfpdfviewer_searchbackbutton Search Back
Sfpdfviewer_searchbarplaceholdertext Search Bar
Sfpdfviewer_clearsearchbutton Clear Search
Sfpdfviewer_rectanglebutton Rectangle
Sfpdfviewer_ellipsebutton Ellipse
Sfpdfviewer_polygonbutton Polygon
Sfpdfviewer_polylinebutton Polyline
Sfpdfviewer_cloudbutton Cloud
Sfpdfviewer_linebutton Line
Sfpdfviewer_arrowbutton Arrow
Sfpdfviewer_shapesbackbutton Shapes Back
Sfpdfviewer_rectanglebackbutton Rectangle Back
Sfpdfviewer_arrowbackbutton Arrow back
Sfpdfviewer_linebackbutton Line back
Sfpdfviewer_ellipsebackbutton Ellipse back
Sfpdfviewer_highlightbutton Highlight Text
Sfpdfviewer_underlinebutton Underline Text
Sfpdfviewer_squigglybutton Squiggly Text
Sfpdfviewer_textmarkupsbackbutton Text Markups Back
Sfpdfviewer_strikethroughbutton Strikethrough Text
Sfpdfviewer_highlighttextbackbutton Text Highlight Back
Sfpdfviewer_underlinetextbackbutton Text Underline back
Sfpdfviewer_strikethroughtextbackbutton Text strikethrough back
Sfpdfviewer_searchbutton Search
Sfpdfviewer_moreoptionsbutton More Options
Sfpdfviewer_bookmarksbutton Bookmarks
Sfpdfviewer_viewmodebutton View Mode
Sfpdfviewer_redoinkbutton Redo Ink
Sfpdfviewer_undoinkbutton Undo Ink
Sfpdfviewer_UndoEraserButton Undo Eraser
Sfpdfviewer_RedoEraserButton Redo Eraser
Sfpdfviewer_done Done
Sfpdfviewer_thicknessonebutton Thickness One
Sfpdfviewer_thicknesthreebutton Thickness Three
Sfpdfviewer_thicknessfivebutton Thickness Five
Sfpdfviewer_thicknesssevenbutton Thickness Seven
Sfpdfviewer_thicknessninebutton Thickness Nine
Sfpdfviewer_cancel Cancel
Sfpdfviewer_signaturepad_done Done
Sfpdfviewer_signaturepad_cancel Cancel
Sfpdfviewer_signaturepad_clear Clear
Sfpdfviewer_backbutton Back
Sfpdfviewer_bookmarksclosebutton Close Bookmarks
Sfpdfviewer_pageupbutton Previous Page
Sfpdfviewer_pagedownbutton Next Page
Sfpdfviewer_continuousButton continuous ViewMode
Sfpdfviewer_singlePageViewButton SinglePage ViewMode
Sfpdfviewer_popupbutton Popup
Sfpdfviewer_eraserbutton Eraser
Sfpdfviewer_popupiconselectorbutton Popup Icon Selector
Sfpdfviewer_commentbutton Comment Icon
Sfpdfviewer_notebutton Note Icon
Sfpdfviewer_insertbutton Insert Icon
Sfpdfviewer_keybutton Key Icon
Sfpdfviewer_paragraphbutton Paragraph Icon
Sfpdfviewer_newparagraphbutton New Paragraph Icon
Sfpdfviewer_helpbutton Help Icon
Sfpdfviewer_custombookmarkoptionbutton Custom bookmark option

To localize the SfPdfViewer, follow the steps in application level:

  1. Add a .resx file.
  2. Convert the platform specific language format to .NET format.
  3. Apply the converted format.

Add a .resx file

In the portable project of your application, add a .resx file inside the resources folder with Build Action -> EmbeddedResource. File name should be Syncfusion control's Namespace + language code format.

For example, to set the culture as French, the file should be named as Syncfusion.SfPdfViewer.XForms.fr-FR.resx.

Adding resx file for PDF Viewer

Based on the language, set the appropriate equivalent text to the static text in the .resx file.

NOTE

You should create and add separate .resx files for individual languages.

resx file of PDF viewer

Convert the platform specific language format to .NET format

To get the localized text from the added .resx file, declare an interface named ILocalize in your PCL project and implement the interface in each platform renderer. This will query the language set in the device using platform specific code and convert to .NET format.

Refer to the following code snippet to declare the interface in PCL project.

public interface ILocalize
{
	CultureInfo GetCurrentCultureInfo();
	void SetLocale(CultureInfo cultureInfo);
}
public class PlatformCulture
{
	public PlatformCulture(string platformCultureString)
	{
		if (!String.IsNullOrEmpty(platformCultureString))
		{
			PlatformString = platformCultureString.Replace("_", "-");// .NET expects dash, not underscore
			var dashIndex = PlatformString.IndexOf("-", StringComparison.Ordinal);
			if (dashIndex > 0)
			{
				var parts = PlatformString.Split('-');
				LanguageCode = parts[0];
				LocaleCode = parts[1];
			}
			else
			{
				LanguageCode = PlatformString;
				LocaleCode = "";
			}
		}
	}

	public string PlatformString
	{
		get; private set;
	}

	public string LanguageCode
	{
		get; private set;
	}

	public string LocaleCode
	{
		get; private set;
	}

	public override string ToString()
	{
		return PlatformString; ;
	}
}

Refer to the following code to implement the interface in Android renderer project.

public class Localize : ILocalize
{
    public void SetLocale(CultureInfo cultureInfo)
    {
        Thread.CurrentThread.CurrentCulture = cultureInfo;
        Thread.CurrentThread.CurrentUICulture = cultureInfo;
    }

    public CultureInfo GetCurrentCultureInfo()
    {
        var netLanguage = "en";
        var androidLocale = Java.Util.Locale.Default;
        netLanguage = AndroidToDotnetLanguage(androidLocale.ToString().Replace("_", "-"));
        // this gets called a lot - try/catch can be expensive so consider caching or something
        CultureInfo cultureInfo = null;
        try
        {
            cultureInfo = new CultureInfo(netLanguage);
        }
        catch
        {
            // iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
            // fallback to first characters, in this case "en"
            try
            {
                var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
                cultureInfo = new CultureInfo(fallback);
            }
            catch
            {
                // iOS language not valid .NET culture, falling back to English
                cultureInfo = new CultureInfo("en");
            }
        }
        return cultureInfo;
    }

    private string AndroidToDotnetLanguage(string androidLanguage)
    {
        var netLanguage = androidLanguage;
        //certain languages need to be converted to CultureInfo equivalent
        switch (androidLanguage)
        {
            case "ms-BN":   // "Malaysian (Brunei)" not supported .NET culture
            case "ms-MY":   // "Malaysian (Malaysia)" not supported .NET culture
            case "ms-SG":   // "Malaysian (Singapore)" not supported .NET culture
                netLanguage = "ms"; // closest supported
                break;
            case "in-ID":  // "Indonesian (Indonesia)" has different code in  .NET 
                netLanguage = "id-ID"; // correct code for .NET
                break;
            case "gsw-CH":  // "Schwiizertüütsch (Swiss German)" not supported .NET culture
                netLanguage = "de-CH"; // closest supported
                break;
                // add more application-specific cases here (if required)
                // ONLY use cultures that have been tested and known to work
        }
        return netLanguage;
    }

    private string ToDotnetFallbackLanguage(PlatformCulture platformCulture)
    {
        var netLanguage = platformCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
        switch (platformCulture.LanguageCode)
        {
            case "gsw":
                netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app
                break;
                // add more application-specific cases here (if required)
                // ONLY use cultures that have been tested and known to work
        }
        return netLanguage;
    }
}

Refer to the following code to implement the interface in iOS renderer project.

public class Localize : ILocalize
{
    public void SetLocale(CultureInfo cultureInfo)
    {
        Thread.CurrentThread.CurrentCulture = cultureInfo;
        Thread.CurrentThread.CurrentUICulture = cultureInfo;
    }

    public CultureInfo GetCurrentCultureInfo()
    {
        var netLanguage = "en";
        if (NSLocale.PreferredLanguages.Length > 0)
        {
            var pref = NSLocale.PreferredLanguages[0];
            netLanguage = iOSToDotnetLanguage(pref);
        }

        // this gets called a lot - try/catch can be expensive so consider caching or something
        CultureInfo cultureInfo = null;
        try
        {
            cultureInfo = new CultureInfo(netLanguage);
        }
        catch
        {
            // iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
            // fallback to first characters, in this case "en"
            try
            {
                var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
                cultureInfo = new CultureInfo(fallback);
            }
            catch
            {
                // iOS language not valid .NET culture, falling back to English
                cultureInfo = new CultureInfo("en");
            }
        }
        return cultureInfo;
    }
    private string iOSToDotnetLanguage(string iOSLanguage)
    {
        var netLanguage = iOSLanguage;
        //certain languages need to be converted to CultureInfo equivalent
        switch (iOSLanguage)
        {
            case "ms-MY":   // "Malaysian (Malaysia)" not supported .NET culture
            case "ms-SG":   // "Malaysian (Singapore)" not supported .NET culture
                netLanguage = "ms"; // closest supported
                break;
            case "gsw-CH":  // "Schwiizertüütsch (Swiss German)" not supported .NET culture
                netLanguage = "de-CH"; // closest supported
                break;
                // add more application-specific cases here (if required)
                // ONLY use cultures that have been tested and known to work
        }
        return netLanguage;
    }

    private string ToDotnetFallbackLanguage(PlatformCulture platCulture)
    {
        var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
        switch (platCulture.LanguageCode)
        {
            // 
            case "pt":
                netLanguage = "pt-PT"; // fallback to Portuguese (Portugal)
                break;
            case "gsw":
                netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app
                break;
                // add more application-specific cases here (if required)
                // ONLY use cultures that have been tested and known to work
        }
        return netLanguage;
    }
}

Implementation of the interface is not required for UWP project, since the resources automatically recognizes the selected language.

Apply the converted format

After setting the root/main page of the application in your MainPage.Xaml.cs file of the PCL project, initialize a new instance of the ResourceManager class and set it to the PdfViewerResourceManager.Manager property to look up into the resources with specified root name in the given assembly. Using DependencyService, call SetLocale() of the implemented interface with necessary language code as parameter.

public partial class MainPage : ContentPage
{
	public MainPage()
	{
		InitializeComponent();
		//The PDF is in the Assets folder of this project. Read it into a stream
		Stream stream = typeof(App).GetTypeInfo().Assembly.GetManifestResourceStream("GettingStarted.Assets.Xamarin_Forms_Succinctly.pdf");
		//Load the stream to PdfViewer
		pdfViewerControl.LoadDocument(stream);
		//Assign the localized string to the specific culture
		PdfViewerResourceManager.Manager=new ResourceManager("GettingStarted.Resources.Syncfusion.SfPdfViewer.XForms", GetType().GetTypeInfo().Assembly);
	}
}

For Android and iOS, it is mandatory to implement the previous steps. However, to set the specific language to the application irrespective of the selected language in the device, use CultureInfo.CurrentUICulture in a specific project of UWP platform.

Refer to the following code example to localize the text in UWP platform.

MainPage.Xaml.cs

public MainPage()
{
    this.InitializeComponent();
    SfPdfViewerRenderer.Init();
    // Applying localization for UWP
    CultureInfo.CurrentUICulture = new CultureInfo("fr");
    LoadApplication(new GettingStarted.App());
}

PDF Viewer with localized text

NOTE

You can refer to our Xamarin PDF Viewer feature tour page for its groundbreaking feature representations. You can also explore our Xamarin.Forms PDF Viewer example to knows the functionalities of each feature.