seam进行国际化改造

每一个用户登录会话都有一个相关的 java.util.Locale 实例(以名为 locale 的组件形式提供给应用程序)。 一般情况下,不需要做任何特别的配置设置locale,Seam 委托JSF来判断当前的活动locale:

  • 如果HTTP请求中有一个相关联的locale(浏览器的locale),并且这个locale在 faces-config.xml 的支持列表中,那么其他会话也使用该locale。
  • 否则,如果在 faces-config.xml 指定了默认的locale, 那么其他会话也使用该locale。
  • 否则,使用服务器的默认locale。

通过Seam的以下几个配置属性来手工设置locale也是你 可能的org.jboss.seam.international.localeSelector.languageorg.jboss.seam.international.localeSelector.countryorg.jboss.seam.international.localeSelector.variant,但是并不推荐这种做法。

然而,允许用户通过应用程序的用户界面来手工设置locale也是很有益处的。Seam提供了内置的功能来覆盖通过上述算法决定的locale。你所要做的只是 在JSP或Facelet的Form中增加以下代码段:

<h:selectOneMenu value="#{localeSelector.language}">
    <f:selectItem itemLabel="English" itemValue="en"/>
    <f:selectItem itemLabel="Deutsch" itemValue="de"/>
    <f:selectItem itemLabel="Francais" itemValue="fr"/>
</h:selectOneMenu>
<h:commandButton action="#{localeSelector.select}" value="#{messages['ChangeLanguage']}"/>

或者,如果你想要一个 faces-config.xml 支持的所有locale的列表,就用:

<h:selectOneMenu value="#{localeSelector.localeString}">
    <f:selectItems value="#{localeSelector.supportedLocales}"/>
</h:selectOneMenu>
<h:commandButton action="#{localeSelector.select}" value="#{messages['ChangeLanguage']}"/>

当在下拉列表中选择一项,并按下按钮后,随后会话中Seam和JSF的locale就被刷新了。

14.2. 标签

JSF 通过使用 <f:loadBundle /> 来支持用户界面标签和描述文本的国际化。这个方法同样可以用在Seam应用程序中。 或者,可以利用Seam的 messages 组件用内嵌的EL表达式来显示模板标签。

14.2.1. 定义标签

Seam提供了一个 java.util.ResourceBundle (以org.jboss.seam.core.resourceBundle 的名字提供给应用程序)。 你需要通过这个指定的资源包来使你的国际化标签可用。默认情况下,Seam 使用名为messages的资源包, 你需要在 messages.propertiesmessages_en.propertiesmessages_en_AU.properties 等文件中定义你的标签。这些文件通常在 WEB-INF/classes 目录下。

因此,在 messages_en.properties中:

Hello=Hello

和在 messages_en_AU.properties中:

Hello=G'day

你可以通过设置Seam的配置属性 org.jboss.seam.core.resourceLoader.bundleNames 为资源包选择一个不同的名字。 甚至可以指定一个资源包名称列表,以深度优先进行消息的搜索。

<core:resource-loader>
    <core:bundle-names>
        <value>mycompany_messages</value>
        <value>standard_messages</value>       
    </core:bundle-names>
</core:resource-loader>

如果想为一个特殊页定义消息,可在以一个和JSF View id同名的资源包中指定,去掉前置 / 和文件扩展名。 这样,如果我们只想在 /welcome/hello.jsp 中显示消息,就把它置于 welcome/hello_en.properties 中。

你还可以在 pages.xml 中指定一个显式的绑定名称:

<page view-id="/welcome/hello.jsp" bundle="HelloMessages"/>

这样,我们就可以在 /welcome/hello.jsp 中使用定义在 HelloMessages.properties 中的消息了。

14.2.2. 标签显示

如果使用Seam的资源包来定义标签,就不用每页再写 <f:loadBundle ... /> 了,可以使用这种简单的形式:

<h:outputText value="#{messages['Hello']}"/>

或者:

<h:outputText value="#{messages.Hello}"/>

更好的一点是,message自身可以包含EL表达式:

Hello=Hello, #{user.firstName} #{user.lastName}
Hello=G'day, #{user.firstName}

你也可以在代码中这样使用消息:

@In private Map<String, String> messages;
@In("#{messages['Hello']}") private String helloMessage;
14.2.3. Faces Messages

facesMessages 组件是一个向用户显示成功或者失败消息的非常方便的途径。 我们之前描述的功能对Faces Messages同样有效:

@Name("hello")
@Stateless
public class HelloBean implements Hello {
    @In FacesMessages facesMessages;
    
    public String sayIt() {
        facesMessages.addFromResourceBundle("Hello");
    }
}

这将根据用户的locale显示 Hello, Gavin King 或者 G'day, Gavin

14.3. 时区

Seam中还有一个session范围的 java.util.Timezone 实例,叫做 org.jboss.seam.international.timezone, 和一个名为 org.jboss.seam.international.timezoneSelector 的用于设置时区的组件。默认情况下,时区取服务器的默认时区。 不幸的是,JSF规范中讲所有的日期和时间都假设是UTC 的,并且显示为UTC,除非使用 <f:convertDateTime> 明确地为其指定时区。 这是一个非常不方便的默认行为。

Seam覆写了这个行为,默认所有的日期和时间都是Seam的时区。另外,Seam提供了 <s:convertDateTime> 标签,用来处理Seam 时区的转化。

14.4. 主题

Seam应用程序可以很方便地改变皮肤。Theme API和本地化API非常相似,但是它们二者的关注点截然不同,一些应用同时支持本地化和主题。

首先,配置所支持的主题集合:

<theme:theme-selector cookie-enabled="true">
    <theme:available-themes>
        <value>default</value>
        <value>accessible</value>
        <value>printable</value>
    </theme:available-themes>
</theme:theme-selector>

注意,第一个是默认的主题。

主题定义在一个和该主题同名的属性文件中。例如,default 主题定义在default.properties中。 default.properties可能是这样定义的:

css ../screen.css
template /template.xhtml

通常主题资源包的内容是CSS样式或图片的路径和facelet模板(不像本地化资源包那样通常是文本)。

现在我们可以在JSP或者Facelet页面中使用这些内容了。例如,一个Facelet页的风格可以这样:

<link href="#{theme.css}" rel="stylesheet" type="text/css" />

或者,当页面定义在一个子目录中时可以这样:

<link href="#{facesContext.externalContext.requestContextPath}#{theme.css}" 
    rel="stylesheet" type="text/css" />

最强大的是,Facelet让我们通过 <ui:composition> 把模板主题化:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    template="#{theme.template}">

正如locale选择器一样,有一个内置的主题选择器允许用户在各主题间自由地切换:

<h:selectOneMenu value="#{themeSelector.theme}">
    <f:selectItems value="#{themeSelector.themes}"/>
</h:selectOneMenu>
<h:commandButton action="#{themeSelector.select}" value="Select Theme"/>
14.5. 使用cookie保存locale和主题设置

locale选择器、主题选择器和时区选择器全都支持持久化,把参数保存到cookie中。仅需要在components.xml中设置 cookie-enabled 配置属性:

<theme:theme-selector cookie-enabled="true">
    <theme:available-themes>
        <value>default</value>
        <value>accessible</value>
        <value>printable</value>
    </theme:available-themes>
</theme:theme-selector>

<international:locale-selector cookie-enabled="true"/>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Seam-carving是一种图像处理技术,它可以对图片进行尺寸调整而不损失图像的重要信息。实现该技术的主要步骤是确定图像中的最小能量路径(seam)并将路径中的像素删除或插入来改变图像的尺寸。以下是一个简单的seam-carving代码实现。 首先,我们需要计算图像的能量矩阵。能量可以用图像中像素的梯度来计算。在本例中,我们采用Sobel算子计算像素梯度。代码如下: ```python import numpy as np from scipy.ndimage import convolve def calc_energy(img): gray = np.average(img, axis=2) h_kernel = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) v_kernel = h_kernel.T h_grad = np.abs(convolve(gray, h_kernel)) v_grad = np.abs(convolve(gray, v_kernel)) energy = h_grad + v_grad return energy ``` 在得到能量矩阵后,我们需要找出最小能量路径。在本例中,我们使用动态规划算法来找到路径。代码如下: ```python def find_seam(energy): M, N = energy.shape seam = np.zeros(M, dtype=int) # 初始化路径矩阵 path = np.zeros((M, N), dtype=int) path[0, :] = energy[0, :] # 动态规划,计算每个像素的最小能量路径 for i in range(1, M): for j in range(N): if j == 0: idx = np.argmin(path[i - 1, j:j + 2]) seam[i] = j + idx path[i, j] = energy[i, j] + path[i - 1, j + idx] elif j == N - 1: idx = np.argmin(path[i - 1, j - 1:j + 1]) seam[i] = j - 1 + idx path[i, j] = energy[i, j] + path[i - 1, j - 1 + idx] else: idx = np.argmin(path[i - 1, j - 1:j + 2]) seam[i] = j - 1 + idx path[i, j] = energy[i, j] + path[i - 1, j - 1 + idx] return seam ``` 最后,我们需要利用找到的最小能量路径来缩小或者扩大图像。代码如下: ```python def seam_carving(img, out_size): in_h, in_w = img.shape[:2] out_h, out_w = out_size # 计算图像能量矩阵 energy = calc_energy(img) if in_w > out_w: # 图像宽度缩小 for i in range(in_w - out_w): # 找到最小能量路径 seam = find_seam(energy) # 将路径上的像素删除 for j in range(in_h): img[j, seam[j]:-1] = img[j, seam[j]+1:] energy[j, seam[j]:-1] = energy[j, seam[j]+1:] if seam[j] > 0: energy[j, seam[j]-1] = calc_energy(img[j:j+1, seam[j]-1:seam[j]])[0, 0] if seam[j] < in_w - 2: energy[j, seam[j]] = calc_energy(img[j:j+1, seam[j]:seam[j]+1])[0, 0] img = img[:, :-1] energy = energy[:, :-1] elif in_w < out_w: # 图像宽度扩大 for i in range(out_w - in_w): # 找到最小能量路径 seam = find_seam(energy) # 插入新像素 mask = np.ones((in_h, in_w), dtype=bool) for j in range(in_h): mask[j, seam[j]] = False img_new = np.zeros((in_h, in_w + 1, 3)) img_new[:, :-1][mask] = img[mask] for j in range(in_h): if seam[j] == 0: img_new[j, seam[j]] = img[j, seam[j]] else: img_new[j, seam[j]] = (img[j, seam[j] - 1] + img[j, seam[j]]) / 2 img_new[j, seam[j] + 1:] = img[j, seam[j]:] img = img_new.copy() # 更新能量矩阵 energy = calc_energy(img) return img ``` 通过上述代码,我们可以实现一个简单的seam-carving算法,对图像进行尺寸调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值