View Javadoc
1   /**
2    * This file Copyright (c) 2013-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.framework.i18n;
35  
36  import info.magnolia.cms.i18n.I18nContentSupport;
37  import info.magnolia.context.Context;
38  import info.magnolia.context.MgnlContext;
39  import info.magnolia.link.LinkUtil;
40  import info.magnolia.objectfactory.Components;
41  import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
42  import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
43  
44  import java.util.ArrayList;
45  import java.util.Collections;
46  import java.util.List;
47  import java.util.Locale;
48  import java.util.Objects;
49  
50  import javax.inject.Provider;
51  import javax.jcr.Node;
52  
53  import org.slf4j.Logger;
54  import org.slf4j.LoggerFactory;
55  
56  import com.vaadin.ui.HasComponents;
57  import com.vaadin.v7.data.Item;
58  
59  /**
60   * Default implementation of {@link info.magnolia.ui.api.i18n.I18NAuthoringSupport}.
61   * Albeit pretending to be generic, it will only do something sophisticated if the related domain
62   * is JCR: the implementation will delegate the resolution to relevant {@link I18nContentSupport} and so on.
63   * In case of non-JCR domains, the default/available locales will be reduced to the one currently
64   * resolvable from the Mgnl context.
65   *
66   * @param <T>
67   *     item type, the impl, however, really works with JCR nodes only.
68   */
69  public class DefaultI18NAuthoringSupport<T> implements I18NAuthoringSupport<T> {
70  
71      private static final Logger log = LoggerFactory.getLogger(DefaultI18NAuthoringSupport.class);
72  
73      private I18nContentSupport i18nContentSupport;
74  
75      private final Provider<Context> contextProvider;
76  
77      private boolean enabled = true;
78  
79      public DefaultI18NAuthoringSupport() {
80          this(Components.getComponent(I18nContentSupport.class), MgnlContext::getInstance);
81      }
82  
83      public DefaultI18NAuthoringSupport(I18nContentSupport i18nContentSupportProvider, Provider<Context> contextProvider) {
84          this.i18nContentSupport = i18nContentSupportProvider;
85          this.contextProvider = contextProvider;
86      }
87  
88      @Override
89      public String deriveLocalisedPropertyName(String base, Locale locale) {
90          return String.format("%s_%s", base, locale.toString());
91      }
92  
93      /**
94       * Returns the available locales for the given page, area or component node.<br>
95       *
96       * Defaults to a singleton set consisting of the default locale only in case of non-JCR items.
97       *
98       * For the case of JCR, please note though that this default implementation exclusively
99       * resolves locales through {@link #i18nContentSupport}, i.e. as configured in /server/i18n/content/locales,
100      * regardless of the passed node.
101      *
102      * @return the list of locales if both i18nAuthoringSupport and i18nContentSupport are enabled, <code>null</code> otherwise.
103      */
104     @Override
105     public List<Locale> getAvailableLocales(T item) {
106         if (item != null && !(item instanceof Node)) {
107             return Collections.singletonList(getDefaultLocale(item));
108         }
109 
110         if (enabled && i18nContentSupport.isEnabled()) {
111             return new ArrayList<>(i18nContentSupport.getLocales());
112         }
113         return Collections.emptyList();
114     }
115 
116     /**
117      * @return the default locale if both i18nAuthoringSupport and i18nContentSupport are enabled,
118      * defaults to {@link MgnlContext#getLocale()} otherwise.
119      */
120     @Override
121     public Locale getDefaultLocale(T item) {
122         if (item != null && !(item instanceof Node)) {
123             return Locale.getDefault();
124         }
125 
126         if (enabled && i18nContentSupport.isEnabled()) {
127             return i18nContentSupport.getDefaultLocale();
128         }
129         return contextProvider.get().getLocale();
130     }
131 
132     @Override
133     public List<Locale> getAvailableLocales(Item item) {
134         if (item instanceof JcrNodeAdapter) {
135             return getAvailableLocales((T) ((JcrNodeAdapter)item).getJcrItem());
136         }
137         return Collections.emptyList();
138     }
139 
140     @Override
141     public Locale getDefaultLocale(Item item) {
142         if (item instanceof JcrNodeAdapter) {
143             return getDefaultLocale((T) ((JcrNodeAdapter) item).getJcrItem());
144         }
145         return contextProvider.get().getLocale();
146     }
147 
148     @Override
149     public boolean isDefaultLocale(Locale locale, Item item) {
150         return Objects.equals(getDefaultLocale(item), locale);
151     }
152 
153     @Override
154     public void i18nize(HasComponents fieldContainer, Locale locale) {
155         log.warn("I18NAuthoringSupport.i18nize is deprecated without a replacement as of version 5.4.1, see e.g. #FormView.Listener.localeChanged(..) implementation for a workaround hint");
156     }
157 
158     @Override
159     public String createI18NURI(Node node, Locale locale) {
160         // we are going to change the context language, this is ugly but is safe as only the current Thread is modified
161         Locale currentLocale = i18nContentSupport.getLocale();
162         String uri;
163         try {
164             // this is going to set the local in the aggregation state and hence wont change the i18nSupport object itself
165             i18nContentSupport.setLocale(locale);
166             uri = LinkUtil.createAbsoluteLink(node);
167         }
168         // make sure that we always reset to the original locale
169         finally {
170             i18nContentSupport.setLocale(currentLocale);
171         }
172         return uri;
173     }
174 
175     public boolean isEnabled() {
176         return enabled;
177     }
178 
179     public void setEnabled(boolean enabled) {
180         this.enabled = enabled;
181     }
182 
183     @Override
184     @Deprecated
185     public Locale getAuthorLocale() {
186         log.warn("I18NAuthoringSupport.getAuthorLocale() is deprecated, returning null. Use SubAppContext.getAuthoringLocale() instead.");
187         return null;
188     }
189 
190     @Deprecated
191     public void setAuthorLocale(Locale locale) {
192         log.warn("I18NAuthoringSupport.setAuthorLocale(Locale) is deprecated, not doing anything. Use SubAppContext.setAuthoringLocale(Locale) instead.");
193     }
194 
195 }