@Override public Property getProperty(Node node, String name) throws RepositoryException { if (!isEnabled()) { return node.getProperty(name); } try { // test for the current language Locale locale = getLocale(); Set<Locale> checkedLocales = new HashSet<Locale>(); // getNextContentLocale() returns null once the end of the locale chain is reached while (locale != null) { Property property = getProperty(node, name, locale); if (!isEmpty(property)) { return property; } else if (locale.equals(getDefaultLocale()) && node.hasProperty(name)) { return node.getProperty(name); } checkedLocales.add(locale); locale = getNextContentLocale(locale, checkedLocales); } } catch (RepositoryException e) { log.error("can't read i18n property {} from node {}", name, node, e); } // return the node data return node.getProperty(name); }
/** * Uses {@link #getNextLocale(Locale)} to find the next locale. If the returned locale is in the * checkedLocales set it falls back to the fall-back locale. If the fall-back locale itself is * passed to the method, the method returns null to signal the end of the chain. */ protected Locale getNextContentLocale(Locale locale, Set<Locale> checkedLocales) { if (locale.equals(getFallbackLocale())) { return null; } Locale candidate = getNextLocale(locale); if (!checkedLocales.contains(candidate)) { return candidate; } return getFallbackLocale(); }
@Override public String toI18NURI(String uri) { if (!isEnabled()) { return uri; } Locale locale = getLocale(); if (isLocaleSupported(locale)) { return toI18NURI(uri, locale); } return uri; }
/** * Removes the prefix. */ @Override public String toRawURI(String i18nURI) { if (!isEnabled()) { return i18nURI; } Locale locale = getLocale(); if (isLocaleSupported(locale)) { return toRawURI(i18nURI, locale); } return i18nURI; }
/** * Extracts the language from the uri. */ @Override public Locale determineLocale() { Locale locale; locale = onDetermineLocale(); // depending on the implementation the returned local can be null (not defined) if (locale == null) { locale = getDefaultLocale(); } // if we have a locale but it is not supported we try to get the closest locale if (!isLocaleSupported(locale)) { locale = getNextLocale(locale); } return locale; }
@Test public void getPropertyWithBothDefaultAndSuffixed() throws RepositoryException { // GIVEN i18nContentSupport.setEnabled(true); i18nContentSupport.setDefaultLocale(Locale.ENGLISH); Node page = session.getRootNode().addNode("test-project"); page.setProperty("title", "globish"); page.setProperty("title_en", "english"); // WHEN i18nContentSupport.setLocale(Locale.ENGLISH); // THEN assertEquals("english", i18nContentSupport.getProperty(page, "title").getString()); }
@Test public void getPropertyWithNextLocaleAndFallback() throws RepositoryException { // GIVEN i18nContentSupport.setEnabled(true); Map<String, Locale> locales = new HashMap<String, Locale>(); locales.put("fr_CA", Locale.CANADA_FRENCH); i18nContentSupport.setLocales(locales); i18nContentSupport.setFallbackLocale(Locale.ENGLISH); Node page = session.getRootNode().addNode("test-project"); page.setProperty("title_fr_CA", "titre"); page.setProperty("abstract_en", "abstract"); // WHEN i18nContentSupport.setLocale(Locale.FRENCH); // THEN assertEquals("titre", i18nContentSupport.getProperty(page, "title").getString()); assertEquals("abstract", i18nContentSupport.getProperty(page, "abstract").getString()); }
@Test public void getPropertyWithExplicitCurrentLocale() throws RepositoryException { // GIVEN i18nContentSupport.setEnabled(true); Node page = session.getRootNode().addNode("test-project"); // a property with the current locale suffix page.setProperty("title_fr", "titre"); // WHEN i18nContentSupport.setLocale(Locale.FRENCH); // THEN assertTrue(i18nContentSupport.hasProperty(page, "title")); assertFalse(i18nContentSupport.hasProperty(page, "NotExistingProperty")); assertEquals("titre", i18nContentSupport.getProperty(page, "title").getString()); }
@Override public Node getNode(Node node, String name) throws RepositoryException { if (isEnabled()) { try { // test for the current language Locale locale = getLocale(); Set<Locale> checkedLocales = new HashSet<Locale>(); // getNextContentLocale() returns null once the end of the locale chain is reached while (locale != null) { String localeSpecificChildName = name + "_" + locale; if (node.hasNode(localeSpecificChildName)) { return node.getNode(localeSpecificChildName); } checkedLocales.add(locale); locale = getNextContentLocale(locale, checkedLocales); } } catch (RepositoryException e) { log.error("can't read i18n node {} from node {}", name, node, e); } } return node.getNode(name); }
/** * Returns the closest locale for which {@link #isLocaleSupported(Locale)} is true. * <ul> * <li>If the locale has a country specified (fr_CH) the locale without country (fr) will be returned.</li> * <li>If the locale has no country specified (fr) the first locale with the same language but specific country (fr_CH) will be returned.</li> * <li>If this fails the fall-back locale is returned</li> * </ul> * Warning: if you have configured both (fr and fr_CH) this method will jiter between this two values. */ protected Locale getNextLocale(Locale locale) { // if this locale defines a country if (StringUtils.isNotEmpty(locale.getCountry())) { // try to use the language only Locale langOnlyLocale = new Locale(locale.getLanguage()); if (isLocaleSupported(langOnlyLocale)) { return langOnlyLocale; } } // try to find a locale with the same language (ignore the country) for (Iterator<Locale> iter = getLocales().iterator(); iter.hasNext(); ) { Locale otherCountryLocale = iter.next(); // same lang, but not the same country as well or we end up in the loop if (locale.getLanguage().equals(otherCountryLocale.getLanguage()) && !locale.equals(otherCountryLocale)) { return otherCountryLocale; } } return getFallbackLocale(); }
@Test public void getDefaultLocaleIfNull() { // GIVEN i18nContentSupport.setLocale(Locale.JAPANESE); // keep default locale null i18nContentSupport.setFallbackLocale(Locale.ENGLISH); // WHEN Locale defaultLocale = i18nContentSupport.getDefaultLocale(); // THEN assertEquals(defaultLocale, Locale.ENGLISH); }
@Test public void getNextLocaleWithFallbackLocale() { // GIVEN i18nContentSupport.setFallbackLocale(Locale.ENGLISH); Map<String, Locale> locales = new HashMap<String, Locale>(); locales.put("fr", Locale.FRENCH); i18nContentSupport.setLocales(locales); // WHEN Locale nextLocale = i18nContentSupport.getNextLocale(Locale.JAPANESE); // THEN assertEquals(Locale.ENGLISH, nextLocale); }
@Test public void testGetLocaleWorksWhenNotInWebContext() { // GIVEN Context ctx = mock(Context.class); MgnlContext.setInstance(ctx); // WHEN Locale result = i18nContentSupport.getLocale(); // THEN assertEquals(i18nContentSupport.getFallbackLocale(), result); }
/** * Test for MAGNOLIA-5993. */ @Test public void getArraysPropertyWithLocale() throws RepositoryException { // GIVEN i18nContentSupport.setEnabled(true); String titles[] = new String[] { "Titel" }; Node page = session.getRootNode().addNode("test-project"); PropertyUtil.setProperty(page, "title_de", Arrays.asList(titles)); // WHEN i18nContentSupport.setLocale(Locale.GERMAN); // THEN assertTrue(i18nContentSupport.getProperty(page, "title").isMultiple()); assertEquals(titles[0], i18nContentSupport.getProperty(page, "title").getValues()[0].getString()); assertEquals(titles.length, i18nContentSupport.getProperty(page, "title").getValues().length); }
@Test public void getNextLocaleFromLanguageLocale() { // GIVEN Map<String, Locale> locales = new HashMap<String, Locale>(); locales.put("fr_CA", Locale.CANADA_FRENCH); i18nContentSupport.setLocales(locales); // WHEN Locale nextLocale = i18nContentSupport.getNextLocale(Locale.FRENCH); // THEN assertEquals(Locale.CANADA_FRENCH, nextLocale); }
@Override public boolean hasProperty(Node node, String name) throws RepositoryException { if (!isEnabled()) { return node.hasProperty(name); } try { // get property using all the rules in getProperty method. If not found, then it doesn't exist. getProperty(node, name); } catch (RepositoryException e) { return false; } return true; }
@Test public void getLocaleIfNull() { // GIVEN // keep current locale null i18nContentSupport.setFallbackLocale(Locale.ENGLISH); // WHEN Locale locale = i18nContentSupport.getLocale(); // THEN assertEquals(locale, Locale.ENGLISH); }
@Override public Locale getDefaultLocale() { if (this.defaultLocale == null) { return getFallbackLocale(); } return this.defaultLocale; }
/** * Test for MAGNOLIA-5931. */ @Test public void getPropertyWithDefaultLocale() throws RepositoryException { // GIVEN i18nContentSupport.setEnabled(true); i18nContentSupport.setDefaultLocale(Locale.GERMAN); i18nContentSupport.setFallbackLocale(Locale.FRENCH); Node page = session.getRootNode().addNode("test-project"); page.setProperty("title", "Titel"); page.setProperty("title_fr", "titre"); // WHEN i18nContentSupport.setLocale(Locale.GERMAN); // THEN assertEquals("Titel", i18nContentSupport.getProperty(page, "title").getString()); }
@Test public void getNextLocaleFromCountrySpecificLocale() { // GIVEN Map<String, Locale> locales = new HashMap<String, Locale>(); locales.put("fr", Locale.FRENCH); i18nContentSupport.setLocales(locales); // WHEN Locale nextLocale = i18nContentSupport.getNextLocale(Locale.CANADA_FRENCH); // THEN assertEquals(Locale.FRENCH, nextLocale); }