将类别重定向到外部URL

Is there some native facility for redirecting categories to external URLs?

Customize >> Permalinks apparently does not support this use.

Why would you redirect a category to an external URL?
What’s the point of having the category if you only need a link?

To have the link displayed as a category without going through all the necessary CSS fiddling to do so without it simply being a category.

The community where I’ll be doing this has a few related Discourse installs that each deal with a different set of topics; I want to more cleanly link them together by creating ‘categories’ that link from each site to each other site.

I briefly looked at doing this and it came down to two alternatives.

  1. Create the category with read only permissions for everyone and put the link into the ‘About this category’ page, maybe including a short paragraph why, like an ‘official’ external support site.

  2. Target and overwrite the link href in a theme component.

I was afraid it would come down to that or doing a rewrite at the server level. I think I may just go with the (somewhat questionable) JavaScript option.

So, related issue: I’ve now implemented a redirect (using JavaScript), but… it works only on refresh, which is clearly suboptimal. At any rate, here’s the code I’m using:

$( document ).ready(function() {
	if ( window.location.href === "https://omnifora.com/c/redirect-politifora" ) {
		window.location.replace( "https://politifora.com/" );
	}
});

As should be obvious from the code, Omnifora is the primary site in this network and I am attempting to redirect a Politifora category on Omnifora to Politifora. I’ve already eliminated caching (browser, server, Cloudflare) as a potential culprit. Is there some quirk in Discourse that would cause this redirect not to trigger?

Yes, being a single-page-app the page only loads once, subsequent loads just replace the page contents. There is a page change API you can hook into:

I’m sure this is the right way to accomplish the redirect, but I am not sure how to write the necessary code. I’ve tried the following and neither seems to work:

api.onPageChange((url) => {
	var targeturl = 'https://politifora.com/';
	if ( url === '/c/redirect-politifora' ) {
		$(location).attr('href',targeturl);
	}
});

and

api.onPageChange((url) => {
	if ( url === '/c/redirect-politifora' ) {
		window.location.replace( 'https://politifora.com/' );
	}
});

if you wanted a redirect this is the way to do it

api.onPageChange((url) => {
	if (url.includes('/c/redirect-politifora')) {
		window.location.replace('https://politifora.com/');
	}
});

however this is kinda slow and won’t run until the page has finished loading, which means users will still see the redirect category. i tried a second way, which is using jQuery to replace the links on the index or anywhere else this category appears.

api.onPageChange(() => {
  $(function(){
    $('a[href*="/c/redirect-politifora').attr(
      'href', 'https://politifora.com/'
    ); 
  });
});

with this you don’t need a redirect, because it modifies href attribute of every redirect-politiflora link in place.

Perhaps I’m missing something, but I tried each of those solutions (both imported from an external .js and dropped in as a customization) and was unable to get either one to work.

where are you inserting them, and do you have the correct script tags around them

I tried both the header (using defer) and the footer (via Customize). When inserted via Customize, I had the code surrounded by <script></script> with type="text/discourse-plugin" set.

Update:

The window.location.replace option is currently live on Omnifora. I am using the following code (yes, I have tried a number of different matching options, but none of them seem to work):

Code Dropped into Customize

<script type="text/discourse-plugin" version="0.8.19">
api.onPageChange((url) => {
    if ( url === 'c/redirect/politifora' || url === '/c/redirect-politifora' || url === 'https://omnifora.com/c/redirect-politifora' || url.includes('/c/redirect-politifora') || url.match('/c/redirect/politifora') ) {
        window.location.replace('https://politifora.com/');
    }
});
</script>

Code as Rendered on Page

<script>Discourse._registerPluginCode('0.8.19', function (api) {

    api.onPageChange(function (url) {
        if (url === 'c/redirect/politifora' || url === '/c/redirect-politifora' || url === 'https://omnifora.com/c/redirect-politifora' || url.includes('/c/redirect-politifora') || url.match('/c/redirect/politifora')) {
            window.location.replace('https://politifora.com/');
        }
    });
});</script>

Given the wrapper that Discourse appears to have applied, it seems the code is partially working, but not performing its intended purpose (i.e., redirecting that category to Politifora). The live code (and its failure to function) can both be viewed on the aforementioned site (the target/affected category is currently at the bottom of the category list).

Is there some specific version of the API I should be using for this?

The following script achieves the intended result when added to </head> via Customize:

<script type="text/discourse-plugin" version="0.8.19">
api.onPageChange(() => {
	if ( window.location.href === "https://omnifora.com/c/redirect-politifora" ) {
		window.location.replace( "https://politifora.com/" );
	}
});
</script>

感谢分享!我正好需要一组子分类,让其中一个充当重定向。由于我的 Customize 已经包含了一个 onPageChange() 检查(用于仅在首页显示标题),这个方案也能适用,而且它并没有硬编码到网站的完整 URL:

<script type="text/discourse-plugin" version="0.8.19">
api.onPageChange((url) => {
       // 检查是否在首页
        if (url === "/" || url === homeRoute) {
              // 对首页执行自定义操作
       } else if ( url=== "/c/redirect-politifora" ) {
             // 分类重定向
             window.location.replace( "https://politifora.com/" );
       } else {
             // 如需,在其他所有页面上执行操作
       }
});
</script>

实际上我并没有使用它,因为在显示子类别浏览器时出现了过于混乱的延迟,导致页面跳转到了其他地方。不过,我也学到了一些东西。

如果您修改路由而不是依赖 api.onPageChange()(该函数似乎在页面渲染后才触发),可能会发现这个问题有所缓解。

参见 Redirect an existing route in a theme component