    001package org.apache.turbine.services.localization;
    002
    003/*
    004 * Licensed to the Apache Software Foundation (ASF) under one
    005 * or more contributor license agreements.  See the NOTICE file
    006 * distributed with this work for additional information
    007 * regarding copyright ownership.  The ASF licenses this file
    008 * to you under the Apache License, Version 2.0 (the
    009 * "License"); you may not use this file except in compliance
    010 * with the License.  You may obtain a copy of the License at
    011 *
    012 *   http://www.apache.org/licenses/LICENSE-2.0
    013 *
    014 * Unless required by applicable law or agreed to in writing,
    015 * software distributed under the License is distributed on an
    016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    017 * KIND, either express or implied.  See the License for the
    018 * specific language governing permissions and limitations
    019 * under the License.
    020 */
    021
    022import java.util.Locale;
    023import java.util.MissingResourceException;
    024
    025import org.apache.commons.logging.Log;
    026import org.apache.commons.logging.LogFactory;
    027import org.apache.fulcrum.localization.LocalizationService;
    028import org.apache.turbine.services.InstantiationException;
    029import org.apache.turbine.services.TurbineServices;
    030import org.apache.turbine.services.pull.ApplicationTool;
    031import org.apache.turbine.util.RunData;
    032/**
    033 * A pull tool which provides lookups for localized text by delegating
    034 * to the configured Fulcrum <code>LocalizationService</code>.
    035 *
    036 * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
    037 * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
    038 * @author <a href="mailto:jon@collab.net">Jon Stevens</a>
    039 */
    040public class LocalizationTool implements ApplicationTool
    041{
    042    /** Logging */
    043    private static Log log = LogFactory.getLog(LocalizationTool.class);
    044    /** Fulcrum Localization component */
    045    private LocalizationService localizationService;
    046    /**
    047     * The language and country information parsed from the request's
    048     * <code>Accept-Language</code> header.  Reset on each request.
    049     */
    050    protected Locale locale;
    051
    052    /**
    053     * Lazy load the LocalizationService.
    054     * @return a fulcrum LocalizationService
    055     */
    056    public LocalizationService getLocalizationService()
    057    {
    058        if (localizationService == null)
    059        {
    060            try
    061            {
    062                localizationService = (LocalizationService)TurbineServices.getInstance()
    063                    .getService(LocalizationService.ROLE);
    064            }
    065            catch (Exception e)
    066            {
    067                throw new InstantiationException("Problem looking up Localization Service:"+e.getMessage());
    068            }
    069        }
    070        return localizationService;
    071    }
    072
    073    /**
    074     * Creates a new instance.  Used by <code>PullService</code>.
    075     */
    076    public LocalizationTool()
    077    {
    078        refresh();
    079    }
    080
    081    /**
    082     * <p>Performs text lookups for localization.</p>
    083     *
    084     * <p>Assuming there is a instance of this class with a HTTP
    085     * request set in your template's context named <code>l10n</code>,
    086     * the VTL <code>$l10n.HELLO</code> would render to
    087     * <code>hello</code> for English requests and <code>hola</code>
    088     * in Spanish (depending on the value of the HTTP request's
    089     * <code>Accept-Language</code> header).</p>
    090     *
    091     * @param key The identifier for the localized text to retrieve.
    092     * @return The localized text.
    093     */
    094    public String get(String key)
    095    {
    096        try
    097        {
    098            return getLocalizationService().getString(getBundleName(null), getLocale(), key);
    099        }
    100        catch (MissingResourceException noKey)
    101        {
    102            log.error(noKey);
    103            return null;
    104        }
    105    }
    106
    107    /**
    108     * Gets the current locale.
    109     *
    110     * @return The locale currently in use.
    111     */
    112    public Locale getLocale()
    113    {
    114        return locale;
    115    }
    116
    117    /**
    118     * The return value of this method is used to set the name of the
    119     * bundle used by this tool.  Useful as a hook for using a
    120     * different bundle than specified in your
    121     * <code>LocalizationService</code> configuration.
    122     *
    123     * @param data The inputs passed from {@link #init(Object)}.
    124     * (ignored by this implementation).
    125     */
    126    protected String getBundleName(Object data)
    127    {
    128        return getLocalizationService().getDefaultBundleName();
    129    }
    130
    131    /**
    132     * Formats a localized value using the provided objects.
    133     *
    134     * @param key The identifier for the localized text to retrieve,
    135     * @param args The objects to use as {0}, {1}, etc. when
    136     *             formatting the localized text.
    137     * @return Formatted localized text.
    138     */
    139    public String format(String key, Object... args)
    140    {
    141        return getLocalizationService()
    142                .format(getBundleName(null), getLocale(), key, args);
    143    }
    144
    145    // ApplicationTool implementation
    146
    147    /**
    148     * Sets the request to get the <code>Accept-Language</code> header
    149     * from (reset on each request).
    150     */
    151    @Override
    152    public void init(Object data)
    153    {
    154        if (data instanceof RunData)
    155        {
    156            // Pull necessary information out of RunData while we have
    157            // a reference to it.
    158            locale = getLocalizationService().getLocale(((RunData) data).getRequest());
    159        }
    160    }
    161
    162    /**
    163     * No-op.
    164     */
    165    @Override
    166    public void refresh()
    167    {
    168        locale = null;
    169    }
    170}