【问题标题】:Tridion and REL: Updating page filename within the page's PublishedUrl propertyTridion 和 REL:在页面的 PublishedUrl 属性中更新页面文件名
【发布时间】:2013-01-09 07:55:02
【问题描述】:

我们要求页面的 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,因为这意味着无法在父网络出版物中管理整个页面。

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

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

我已尝试通过自定义解析器执行此操作,但是,在此级别上,页面.PublishedUrl 属性似乎已由 CM 建立并且不能被覆盖。所以更新 page.FileName 属性没有任何用处。

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

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

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

【问题讨论】:

  • 认为您可能不得不在部署者方面执行此操作。您可以使用部署程序扩展来更改传输包中页面的文件名(这里是dragons:未记录且可能不受支持)...

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


【解决方案1】:

按照上面 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;
    }
}

【讨论】:

    【解决方案2】:

    也许是另一种选择:

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

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

    /mysite/%postname%/

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

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

    【讨论】:

    • 感谢约翰的建议。但是,我应该提到的另一个要求是,我们不能进行超过 1 次 odata 命中才能获取页面。将其保存在 custommeta 中需要先点击 CustomMetas 实体,然后再点击 Pages 实体。我们希望避免这种情况,并且只使用我们可以 $filter 所依据的参数。
    猜你喜欢
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多