> 
> ----- Original Message -----
> From: "Leandro Rodrigo Saad Cruz" <[EMAIL PROTECTED]>
> To: "Turbine Users List" <[EMAIL PROTECTED]>
> Sent: Tuesday, March 19, 2002 3:52 PM
> Subject: Re: Localization
> 
> 
> > You can use the Localization accessor with any locale you would like.
> > Maybe you can change TLocalizationService.java or LocalizationTool.java
> > to allow some order or user preference regarding localized objects.
> > I created a class called LocaleHelper that has the business logic used
> > to pick up a locale acording to values in user session and http headers.
> > If you wnat I can send it to you.

Ok.. that's what I've done.
I need to grab *localized objects and maybe choose between **localized
templates

* to accomplish this I wrote LocalizationHelper, this class is used in
behalf of *new* LocalizationTool and encapsulates the logic that chooses
locales.

** I wrote a new Screen that tries to find different templates accordign
to some locale info. For example : locale=pt_BR, then
SomeTemplate-pt_BR.vm is looked up, then SomeTemplate.vm

OBS : you will have to change the package of this files and possibly
some code (chanbe ACCEPTED_LOACES for example) to make it work.

Want any help ??

To see it working visit
http://www.intercontinental.ind.br:8180/inter/servlet/main
this site is supposed to be viewed in English and Portuguese

-- 
Leandro Rodrigo Saad Cruz
IT - Inter Business Tecnologia e Servicos (IB)
http://www.ibnetwork.com.br
package br.com.ibnetwork.intercontinental.modules.screens;

//APP
import br.com.ibnetwork.intercontinental.services.localization.LocalizationHelper;

//T2
import org.apache.turbine.util.RunData;
import org.apache.turbine.util.Log;
import org.apache.turbine.modules.screens.VelocityScreen;
import org.apache.turbine.services.template.TurbineTemplate;
import org.apache.turbine.services.velocity.TurbineVelocity;
import org.apache.velocity.context.Context;
import org.apache.velocity.app.Velocity;
import org.apache.ecs.ConcreteElement;

//JAVA
import java.util.Locale;
import java.io.File;

/**
 * This module is responsible for searching a template file accordign to LocalizationHelper.getLocale()
 * <br>
 * This way we can stil use links like $link.setPage("SomeTemplate.vm") and this module will handle the template engine the right template. For Example : 
 * <br> 
 * <b>USER_LOCALE = pt_BR</b>
 * <br>
 * search for : SomeTemplate-pt_BR.vm, then SomeTemplate.vm ....
 *
 * @author <a href="mailto:[EMAIL PROTECTED]";>Leandro Rodrigo Saad Cruz</a>
 */
public class IntercontinentalVelocityScreen extends VelocityScreen
{

    /**
     * Este metodo sera executado apos os metodos dos screens que estendem esta classe<br>
     * Sua funcao eh tentar localizar um template com o mesmo nome do presente em RunData, mas com conteudo sensivel ao locale correto.
     * O locale pesquisado pode variar de acordo com as regras em LocalizationHelper. 
     * Este módulo apenas faz uma tentativa de mudar o template, caso o template-locale não exista, o template original será executado
     */
    public void setTemplateLocalizationExtension(RunData data)
    {
        Locale locale = LocalizationHelper.getLocale(data);
        Log.debug("debug","IntercontinentalScreen - Searching for new template for locale["+locale+"]");
        if(locale != null)
        {
            try
            {
                //caso algum locale esteja disponivel nos tentaremos achar outros template
                String templateName = TurbineTemplate.getScreenTemplateName(data.getTemplateInfo().getScreenTemplate());
                Log.debug("debug","IntercontinentalScreen - original template["+templateName+"]");
                data.setScreenTemplate(composeLocaleInfoAndTemplateName(templateName,locale));
            }
            catch(Exception e)
            {
                Log.debug("Erro",e);
                //em caso de erro, o template original sera pesquisado
            }
        }
    }

    /**
     * This method is called by the Screenloader to construct the
     * Screen.
     *
     * @param data Turbine information.
     * @return A ConcreteElement.
     * @exception Exception, a generic exception.
     */
    public ConcreteElement doBuild( RunData data )
        throws Exception
    {
        Log.debug("debug","IntercontinentalScreen - Executing doBuild(data)");
        ConcreteElement out = null;
        
        try
        {
            doBuildTemplate(data);
            setTemplateLocalizationExtension(data);
            out = buildTemplate(data);
        }
        finally
        {
            doPostBuildTemplate(data);
        }

        return out;
    }
    
    private String composeLocaleInfoAndTemplateName(String templateName,Locale locale)
    {
        int pathSeparatorPosition = templateName.lastIndexOf("/");
        if(pathSeparatorPosition >= 0)
        {
            
            String minusPath = templateName.substring(pathSeparatorPosition + 1);
            String path = templateName.substring(0,pathSeparatorPosition+1);
            Log.debug("debug","IntercontinentalScreen - path["+path+"] name["+minusPath+"]");
            int dotPosition = minusPath.lastIndexOf(".");
            StringBuffer sb = new StringBuffer();
            sb.append(path)
                .append(minusPath.substring(0,dotPosition))
                .append("-")
                .append(locale)
                .append(minusPath.substring(dotPosition));
            String newTemplateName = sb.toString();
            if(Velocity.templateExists("/screens"+newTemplateName))
            {
                Log.info("debug","IntercontinentalScreen - localizedTemplateName found ["+newTemplateName+"] ");
                return newTemplateName;
            }
        }
        Log.info("debug","IntercontinentalScreen - localizedTemplateName found ["+templateName+"] ");
        return templateName;
    }

}
package br.com.ibnetwork.intercontinental.services.localization;

//T2
import org.apache.turbine.util.Log;
import org.apache.turbine.util.RunData;
import org.apache.turbine.services.localization.Localization;

//JAVA
import java.util.Locale;
import java.util.StringTokenizer;

/**
 * This class is a helper tool to be used when you have to decide which Locale to choose.
 * This implementation follows this criteria : <br>
 * i - first it checks to see if there is locale in the user session <br>
 * ii - then it tries to build a locale from HTTP headers <br>
 * iii - then it uses the default locale in TR.conf <br>
 *
 * @author <a href="mailto:[EMAIL PROTECTED]";>Leandro Rodrigo Saad Cruz</a>
 */
public class LocalizationHelper
{
    /** 
     * Key used to put a Locale Object 
     * into the session and used as a form field name 
     * OBS : if you want this to work between user logins you will have to patch Turbine.java to not exclude this key/val from Session
     */
    public static final String USER_LOCALE = "user.locale";


    /**
     * Key used to define the locale separator char
     */
    public static final String SEPARATOR = "_";


    /**
     * All locales that we are prepard to handle PORTUGUES and ENGLISH
     * <br>
     * OBS : Remenber, if you want do add the locales to this array you will have to add new templates to your system too
     */
    public static Locale[] ACCEPTED_LOCALES = { new Locale("pt","BR"), Locale.US,Locale.ENGLISH };

    /**
     * Performs Locale selection
     */
    public static Locale getLocale(RunData data)
    {
        //Session
        Locale locale = (Locale) ((RunData)data).getSession().getValue(USER_LOCALE);
        
        //HEADERS HTTP
        if(locale == null)
        {
            locale = Localization.getLocale( ((RunData) data).getRequest() );
            boolean accepted = false;
            for(int i=0 ; i < ACCEPTED_LOCALES.length ; i++)
            {
                Log.debug("debug","LocalizationHelper: searching locale["+ACCEPTED_LOCALES[i]+"] in ACCEPTED list");
                if(locale.equals(ACCEPTED_LOCALES[i]))
                {
                    accepted = true;
                    break;
                }
            }
            locale = (accepted == false ? null : locale);
        }
        
        //TR.conf
        if(locale == null)
        {
            locale = Localization.getBundle(Localization.getDefaultBundleName()).getLocale();
        }
        return locale;
    }

    /**
     * helper method used to build a locale from HTTP HEADERS
     * @return a new locale obj or null when an error occur 
     */
    public static Locale buildLocaleFromParameter(String param)
    {
        if(param != null)
        {
            Locale locale;
            StringTokenizer st = new StringTokenizer(param,SEPARATOR);
            int total = st.countTokens(); 
            String tokens[] = new String[total];
            while (st.hasMoreTokens()) 
            {
                String token = st.nextToken();
                Log.debug("debug","TOKEN ["+token+"]");
                tokens[--total] = token;
            }
            if(tokens.length == 2)
            {
                return new Locale(tokens[1],tokens[0]);
            }
            if(tokens.length == 3)
            {
                return new Locale(tokens[2],tokens[1],tokens[0]);
            }
        }
        return null;
    }
}
package br.com.ibnetwork.intercontinental.services.localization;

//APP

//T2
import org.apache.turbine.services.localization.Localization;
import org.apache.turbine.services.pull.ApplicationTool;
import org.apache.turbine.om.security.User;
import org.apache.turbine.util.Log;
import org.apache.turbine.util.RunData;


//JAVA
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * Localization Tool usado nos templates para disponibilizar conteúdo localizado com ajuda de 
 * {@link br.com.ibnetwork.intercontinental.services.localization.LocalizationHelper}
 *
 * @author <a href="mailto:[EMAIL PROTECTED]";>Leandro Rodrigo Saad Cruz</a>
 */
public class LocalizationTool implements ApplicationTool
{


    /**
     * The language and country information parsed from the request's
     * <code>Accept-Language</code> header.  Reset on each request.
     */
    protected Locale locale;

    /**
     * The bundle for this request.
     */
    private ResourceBundle bundle;

    /**
     * The name of the bundle for this tool to use.
     */
    private String bundleName;

    /**
     * Creates a new instance.  Used by <code>PullService</code>.
     */
    public LocalizationTool()
    {
        locale = null;
        bundle = null;
        bundleName = null;
    }

    /**
     * <p>Performs text lookups for localization.</p>
     *
     * <p>Assuming there is a instance of this class with a HTTP
     * request set in your template's context named <code>l10n</code>,
     * the VTL <code>$l10n.HELLO</code> would render to
     * <code>hello</code> for English requests and <code>hola</code>
     * in Spanish (depending on the value of the HTTP request's
     * <code>Accept-Language</code> header).</p>
     *
     * @param key The identifier for the localized text to retrieve.
     * @return The localized text.
     */
    public String get(String key)
    {
        try
        {
            //Log.debug("service","Localization tool :Bundle["+bundleName+"]=["+bundle+"] used for key["+key+"] and locale["+locale+"]");
            return bundle.getString(key);
        }
        catch (MissingResourceException noKey)
        {
            Log.warn("service","Missing Resource",noKey);
            return null;
        }
    }

    /**
     * The return value of this method is used to set the name of the
     * bundle used by this tool.  Useful as a hook for using a
     * different bundle than specifed in your
     * <code>LocalizationService</code> configuration.
     *
     * @param data The inputs passed from {@link #init(Object)}.
     * (ignored by this implementation).
     */
    protected String getBundleName(Object data)
    {
        return Localization.getDefaultBundleName();
    }

    
    /**
     * Tool initialization
     * <BR>
     * GLOBAL
     * <blockquote>
     * Locale comes from TR.conf
     * </blockquote>
     * <BR>
     * REQUEST
     * <blockquote>
     *  Check if user.locale is in Session, otherwise build a locale from HTTP HEADERS
     * </blockquote>
     *
     */
    public final void init(Object data)
    {
        if(data == null)
        {
            Log.debug("service","Localization tool initializing with scope GLOBAL");
         
            //bundle default em TR.conf since no request data is available
            bundle = Localization.getBundle(Localization.getDefaultBundleName());
        }

        if(data instanceof User)
        {
            Log.debug("service","Localization tool initializing with scope SESSION");
            // Pull necessary information out of Session.
        }
        
        if (data instanceof RunData)
        {
            Log.debug("service","Localization tool initializing with scope REQUEST");
            
            // Pull necessary information out of RunData while we have a reference to it.
            locale = LocalizationHelper.getLocale((RunData)data);
            bundleName = getBundleName(data);

            //bundle acoording to request information
            bundle = Localization.getBundle(bundleName, locale);
            Log.debug("service","Localization tool initialized with bundleName["+bundleName+"] locale["+locale+"]");
        }
    }

    /**
     * No-op.
     */
    public void refresh()
    {
        Log.debug("service","Localization tool refreshing...");
    }
    
    /**
     * helper method to be used inside templates
     */
    public String getUserLocale()
    {
        return LocalizationHelper.USER_LOCALE;
    }

}

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to