4

我们有一个页面的 url 需要本地化/翻译的要求。我们现有的机制依赖于实际发布的 url 来通过 oData 检索页面。用一个简化的例子来澄清一下:我们在前端有一些逻辑,它接受请求 url(它没有文件扩展名,附加一个 .html 扩展名,例如:

/my-awesome-path/my-awesome-page

现在变成

/my-awesome-path/my-awesome-page.html

然后,该逻辑使用查询从 oData 中提取页面

/odata.svc/Pages?$filter=url eq '/my-awesome-path/my-awesome-page.html'

我们有更多的逻辑来解析这个 SEO 友好的 url 并获取 MVC 控制器函数参数和其他诸如此类的东西,但这与这里无关。

我们的要求是我们不能对页面进行本地化以为其提供翻译后的 url,因为这意味着整个页面无法在父 Web 出版物中进行管理。

为了获得通向页面文件名的本地化路径,我们只需本地化 SG。困难在于页面文件名。在页面的元数据上,我们有一个链接的“可本地化元数据”组件,其中包含一个用于提供本地化页面文件名的字段。

我们要做的是在发布/部署过程中更新页面的 URL 属性,以使用来自此链接元数据组件的本地化页面文件名更新页面的已发布 url(假设我们在任何阶段都可以访问本地化文件名字段的值在开始发布到承诺部署之间)。

我已经尝试通过自定义解析器执行此操作,但是,在此级别上,CM 已建立 page.PublishedUrl 属性并且无法覆盖。所以更新 page.FileName 属性并没有做任何有用的事情。

我还尝试将 Broker DB 中 PAGE 表中的 URL 列直接更新为不同的名称,似乎一切都在继续工作,包括动态链接和取消发布页面。显然写一个存储扩展或者一个部署扩展来通过jdbc直接更新数据库是不可接受的。

以下是我正在考虑的选项: 1) 尝试部署程序扩展并使用 Tridion API 更新 url 属性 2) 尝试编写自定义渲染器来执行 url 替换逻辑而不实际更新代理中的 url。我不赞成这样做,因为每次都需要请求时间处理。

我的问题是:更新页面 url 属性的最合适方法是什么?使用 Tridion API 编写自定义部署程序来更新 URL 属性是否会像 Resolver 那样导致我陷入死胡同?

4

2 回答 2

3

按照上面 Nuno 评论中的要点,我决定不使用自定义部署程序,并使用事件系统的 2 个事件订阅解决了这个问题。在页面发布时,我首先本地化页面,从本地化链接元数据组件中获取本地化文件名并保存页面。然后在随后的事件中,我只是取消了页面的本地化。这是我的工作代码:

[TcmExtension("Publish or Unpublish Events")]
public class PublishOrUnpublishEvents : TcmExtension
{
    public PublishOrUnpublishEvents()
    {
        EventSystem.Subscribe<Page, PublishEventArgs>(SetLocalizedPageFileName, EventPhases.Initiated);
        EventSystem.Subscribe<Page, SetPublishStateEventArgs>(UnlocalizePageOncePublished, EventPhases.Initiated);
    }


    public void SetLocalizedPageFileName(Page page, PublishEventArgs args, EventPhases phase)
    {
        string localFilename = GetLocalilizedFileNameFromPageMetadata(page);
        if (!string.IsNullOrEmpty(localFilename))
        {
            page.Localize();
            if (page.TryCheckOut())
            {
                page.FileName = localFilename;
                page.Save(true);
            }
        }
    }

    public void UnlocalizePageOncePublished(Page page, SetPublishStateEventArgs args, EventPhases phase)
    {
        string localFilename = GetLocalilizedFileNameFromPageMetadata(page);
        if (!string.IsNullOrEmpty(localFilename))
            page.UnLocalize();
    }

    private string GetLocalilizedFileNameFromPageMetadata(Page page)
    {
        string localFilename = string.Empty;
        if (page.Metadata != null)
        {
            ItemFields fields = new ItemFields(page.Metadata, page.MetadataSchema);
            if (fields.Contains("LocalizableMeta"))
            {
                ComponentLinkField localMetaField = fields["LocalizableMeta"] as ComponentLinkField;
                Component component = localMetaField.Value;
                ItemFields compFields = new ItemFields(component.Content, component.Schema);
                if (compFields.Contains("LocalizedPageFilename"))
                {
                    SingleLineTextField fileNameTextField = compFields["LocalizedPageFilename"] as SingleLineTextField;
                    localFilename = fileNameTextField.Value;
                }
            }
        }
        return localFilename;
    }
}
于 2013-01-11T04:48:14.990 回答
1

也许另一种选择:

存储本地化 URL 具有页面的附加元数据字段,为已发布页面保持相同的物理 URL。

我看到您的要求是避免子页面的本地化,我喜欢在 wordpress 中可以全局输入 URL 工作方式的方式,例如:

/我的网站/ %postname%/

在 SDL Tridion 中构建类似的东西会很酷,其中可以提取内容标题并在内容 URL 中使用。

无论哪种方式,如果您必须编写一个采用“友好 URL”并查找实际 URL 的系统,我认为这将非常简单。

于 2013-01-09T08:41:01.823 回答