Tridion和REL:在页面的PublishedUrl属性中更新页面文件名

时间:2013-01-09 07:55:02

标签: tridion odata tridion-2011 tridion-content-delivery

我们要求页面的网址需要可本地化/翻译。我们现有的机制依赖于实际发布的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控制器函数参数和其他诸如此类的东西,但这与此无关。

我们的要求是我们无法对网页进行本地化以为其提供已翻译的网址,因为这意味着无法在父网络出版物中管理整个网页。

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

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

我尝试通过自定义解析程序执行此操作,但是,在此级别,似乎已经由CM建立了page.PublishedUrl属性,并且无法覆盖。所以更新page.FileName属性没有任何用处。

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

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

我的问题是:更新页面网址属性的最合适方法是什么?使用Tridion API编写自定义部署程序来更新URL属性会让我陷入死胡同,就像解析器一样吗?

2 个答案:

答案 0 :(得分: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;
    }
}

答案 1 :(得分:1)

也许是另一种选择:

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

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

/ mysite的/ %postname% /

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

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