The sitecore configuration code below works well in normal mode.
<encodeNameReplacements>
<replace mode="on" find=" " replaceWith="-" />
</encodeNameReplacements>
In Page editor mode the (Spaces) " " or not replaced with "-".
In Page Editor Mode:
If i try to remove image and insert new one; image is not displayed until i saved the page because the (Spaces) " " or not replaced with "-".
Am i missing anything, any ideas will be appreciated.
I had a problem with the encodeNameReplacements messing up the media paths until I found this article.
After implementing this code in our project a dash will replace the %20 and the media images will still render.
Sitecore 7.2 Upgrade Media Library Gotcha
http://getfishtank.ca/blog/sitecore-7-2-upgrade-encoding-media-library-item-names
While upgrading a client to Sitecore 7.2 this section of the release notes gave us pause:
Media API
When rendering media URLs, the system did not use the configuration in the encodeNameReplacements section to replace special characters in the URLs.
This has been fixed so that media URLs also use the encodeNameReplacements configuration. (323105, 314977)
Summary:
media library URLs now use the encodeNameReplacements configuration.
If any one run into this problem; Look for any custom media code written on your site. I got the below custom code causing the problem:
public class MediaProvider : Sitecore.Resources.Media.MediaProvider
{
public override string GetMediaUrl(Sitecore.Data.Items.MediaItem item, Sitecore.Resources.Media.MediaUrlOptions options)
{
string url = base.GetMediaUrl(item, options);
if (!(Sitecore.Context.PageMode.IsNormal && options.UseItemPath))
{
return url;
}
}
}
Working when Changed to
public class MediaProvider : Sitecore.Resources.Media.MediaProvider
{
public override string GetMediaUrl(Sitecore.Data.Items.MediaItem item, Sitecore.Resources.Media.MediaUrlOptions options)
{
string url = base.GetMediaUrl(item, options);
if (options.UseItemPath)
{
return url;
}
}
}
Related
I have a website(built with OpenCart) with multiple languages, e.g. English, German, French.
Users can change language using default functionality of the OpenCart - clicking on language icons on top.
Is it possible to send users automaticaly (so they don't have to click on the flag) from :
Germany to German version of the website
France to French version of the website
(English language is default)
Is there an URL I can use for these languages if the default page is for example http://mystore.com ?
(I noticed that when I click on the language icon the URL is not changing - it's the same for all languages)
Nowadays opencart doesn't support this function, but in the past , older versions of Opencart did have this function.
If you want to include this function in your website you will have to do the following:
Edit this file:
catalog/controller/module/language.php
find this:
class ControllerModuleLanguage extends Controller {
protected function index() {
if (isset($this->request->post['language_code'])) {
before the "if", you will have to include the following :
if (isset($this->request->get['lang'])) {
$this->session->data['language'] = $this->request->get['lang'];
if (isset($_SERVER['HTTP_REFERER']) && (strpos($_SERVER['HTTP_REFERER'], $this->config->get('config_url')) !== false) ) {
$this->redirect($_SERVER['HTTP_REFERER']);
} else {
$this->redirect($this->url->link('common/home'));
}
} else {
The source
An example of website with this code:
http://incomingtospain.com/madrid&lang=de
http://incomingtospain.com/madrid&lang=ru
This website has 8 idioms and you can access by different url, with this variable "lang" &lang=es &lang=en ... &lang=de &lang=ru
I think language is set in session variable
For the functionality you mentioned will be achive in following way:
Use the HTML5 geolocation to detect the location of user
Research in opencart to set the language function
after all done place your code using VQMOD if you want to do it in proper way
or you can also edit your core opencart files( Not recommended)
if the browser doesn't support geolocation or they refuse to share their location just load the default language.
With OpenCart 2.0, you must work on the file index.php (in your website root) and place this code :
if (isset($request->get['lang']) && array_key_exists($request->get['lang'], $languages)) {
$session->data['language'] = $request->get['lang'];
}
between line 155 and line 157
Line 153 to 154 :
foreach ($query->rows as $result) {
$languages[$result['code']] = $result;
}
(you add here the new code)
Line 157 :
if (isset($session->data['language']) && array_key_exists($session->data['language'], $languages)) {
Line 158 :
$code = $session->data['language'];
Is there any way to parametise the Datasource for the 'source' field in the Template Builder?
We have a multisite setup. As part of this it would save a lot of time and irritation if we could point our Droptrees and Treelists point at the appropriate locations rather than common parents.
For instance:
Content
--Site1
--Data
--Site2
--Data
Instead of having to point our site at the root Content folder I want to point it at the individual data folders, so I want to do something like:
DataSource=/sitecore/content/$sitename/Data
I can't find any articles on this. Is it something that's possible?
Not by default, but you can use this technique to code your datasources:
http://newguid.net/sitecore/2013/coded-field-datasources-in-sitecore/
You could possibly use relative paths if it fits with the rest of your site structure. It could be as simple as:
./Data
But if the fields are on random items all over the tree, that might not be helpul.
Otherwise try looking at:
How to use sitecore query in datasource location? (dynamic datasouce)
You might want to look at using a Querable Datasource Location and plugging into the getRenderingDatasource pipeline.
It's really going to depend on your use cases. The thing I like about this solution is there is no need to create a whole bunch of controls which effectively do he same thing as the default Sitecore ones, and you don't have to individually code up each datasource you require - just set the query you need to get the data. You can also just set the datasource query in the __standard values for the templates.
This is very similar to Holger's suggestion, I just think this code is neater :)
Since Sitecore 7 requires VS 2012 and our company isn't going to upgrade any time soon I was forced to find a Sitecore 6 solution to this.
Drawing on this article and this one I came up with this solution.
public class SCWTreeList : TreeList
{
protected override void OnLoad(EventArgs e)
{
if (!String.IsNullOrEmpty(Source))
this.Source = SourceQuery.Resolve(SContext.ContentDatabase.Items[ItemID], Source);
base.OnLoad(e);
}
}
This creates a custom TreeList control and passes it's Source field through to a class to handle it. All that class needs to do is resolve anything you have in the Source field into a sitecore query path which can then be reassigned to the source field. This will then go on to be handled by Sitecore's own query engine.
So for our multi-site solution it enabled paths such as this:
{A588F1CE-3BB7-46FA-AFF1-3918E8925E09}/$sitename
To resolve to paths such as this:
/sitecore/medialibrary/Product Images/Site2
Our controls will then only show items for the correct site.
This is the method that handles resolving the GUIDs and tokens:
public static string Resolve(Item item, string query)
{
// Resolve tokens
if (query.Contains("$"))
{
MatchCollection matches = Regex.Matches(query, "\\$[a-z]+");
foreach (Match match in matches)
query = query.Replace(match.Value, ResolveToken(item, match.Value));
}
// Resolve GUIDs.
MatchCollection guidMatches = Regex.Matches(query, "^{[a-zA-Z0-9-]+}");
foreach (Match match in guidMatches)
{
Guid guid = Guid.Parse(match.Value);
Item queryItem = SContext.ContentDatabase.GetItem(new ID(guid));
if (item != null)
query = query.Replace(match.Value, queryItem.Paths.FullPath);
}
return query;
}
Token handling below, as you can see it requires that any item using the $siteref token is inside an Site Folder item that we created. That allows us to use a field which contains the name that all of our multi-site content folders must follow - Site Reference. As long at that naming convention is obeyed it allows us to reference folders within the media library or any other shared content within Sitecore.
static string ResolveToken(Item root, string token)
{
switch (token)
{
case "$siteref":
string sRef = string.Empty;
Item siteFolder = root.Axes.GetAncestors().First(x => x.TemplateID.Guid == TemplateKeys.CMS.SiteFolder);
if (siteFolder != null)
sRef = siteFolder.Fields["Site Reference"].Value;
return sRef;
}
throw new Exception("Token '" + token + "' is not recognised. Please disable wishful thinking and try again.");
}
So far this works for TreeLists, DropTrees and DropLists. It would be nice to get it working with DropLinks but this method does not seem to work.
This feels like scratching the surface, I'm sure there's a lot more you could do with this approach.
In the Workbox we have “Open” and “Preview” functionality.
Is it possible to modify the “Open” functionality to open the content editor item in a new browser tab, rather than displaying the “Content Editor” in a pop-up?
That's possible:
First, find out what code is used for the workbox. This can be done by opening the Workbox.xml (located in webroot/sitecore/shell/Applications/Workbox) file.
You'll see something like
<CodeBeside Type="Sitecore.Shell.Applications.Workbox.WorkboxForm,Sitecore.Client"/>
By using Reflector on the WorkboxForm class I can see that the following happens when you click 'Open' in workbox:
webControl["Click"] = string.Concat(new object[] { "Open(\"", item.ID, "\", \"", item.Language, "\", \"", item.Version, "\")" });
So you'll need to create your own version of a WorkboxForm, inheriting Sitecore's WorkboxForm class and override the Open method, something like so:
protected new void Open(string id, string language, string version)
{
// Your code goes here
}
In Workbox.xml, change the CodeBeside to point to your new class.
For more information on custom functionality in the Workbox, I can recommend reading through this article, which has a lot of detail in it, also on other methods in the Workbox.
There's also another useful question on StackOverflow already. The comment on the accepted answer points out you can put your Workbox.xml file into /sitecore/shell/override.
Please note that this is based on Sitecore 6.5 update 5, it might differ a bit in other versions.
In the Appconfig/Commands.config you can find commands and classes related to them.
I have reflected some commands like preview, open and understood what's going on internally.
e.g. name="item:open" type="Sitecore.Shell.Framework.Commands.ContentEditor.OpenItem,Sitecore.Kernel"
And I have overridded the "Open" mwthod in the workbox as follows to open the content editor item in the new tab,
...
UrlString urlString = new UrlString("/sitecore/shell/Applications/Content%20Editor");
urlString.Append("id", id);
urlString.Append("vs", version);
urlString.Append("ro", sectionId);
urlString.Append("la", language);
urlString.Append("fo", id);
SheerResponse.Eval("window.open('" + (object)urlString + "', '_blank')");
...
It works!!!!!
Anyone knows how to generate links in sitecore with ID instead of item path?
If you use GetMediaUrl method from the API, I can get this URL:
/~/media/Images/Archive/content/News and Events/News_and_Events_Level2/20070419162739/iwhiz3.jpg
The problem with this approach is that if someone changes the media item name, removes it somewhere or deletes it, the above link will break.
I notice if I insert a media link from rich text editor, I get the link as below:
/~/media/14BDED00E4D64DFD8F74019AED4D74EB.ashx
The second link is better because it's using the item id, so if the actual media item is renamed, removed, or deleted, all related links will be updated too. On top of that, when Sitecore renders the page, it will actually convert the above link and display the item path so it's readable.
I'm using Sitecore 6.5 and currently doing content migration so I need to make sure all internal links are updated properly.
May I know if there is a method to generate the second link by using sitecore API?
Thanks!
The GetMediaItemUrl extension method seems to give you what you want.
public static class ItemExtensions
{
public static string GetMediaItemUrl(this Item item)
{
var mediaUrlOptions = new MediaUrlOptions() { UseItemPath = false, AbsolutePath = true };
return Sitecore.Resources.Media.MediaManager.GetMediaUrl(item, mediaUrlOptions);
}
}
[TestFixture]
public class when_using_items_extensions
{
[Test]
public void a_url_based_on_media_item_id_can_be_generated()
{
// Arrange
Database db = global::Sitecore.Configuration.Factory.GetDatabase("master");
Item item = db.GetItem("/sitecore/media library/Images/MyImage");
// Act
var mediaUrl = item.GetMediaItemUrl();
// Assert
Assert.That(mediaUrl, Is.EqualTo("/~/media/17A1341ABEEC46788F2159843DCEAB03.ashx"));
}
}
These are called dynamic links and you can normally generate them using the LinkManager e.g:
Sitecore.Links.LinkManager.GetDynamicUrl(item)
.. but I'm not sure of the method to do this with Media links (there probably is one but I cant seem to find it and its not on MediaManager) but the basic syntax is:
"/~/media/" + item.ID.ToShortID() + ".ashx"
If you always want to use ID's instead of paths, you can change this setting in webconfig to false (like this):
<setting name="Media.UseItemPaths" value="false"/>`
Here is what the webconfig describes about it:
MEDIA - USE ITEM PATHS FOR URLS
This setting controls if item paths are used for constructing media URLs.
If false, short ids will be used.
Default value: true
Then you can use the default implementation (without additional parameters):
Sitecore.Resources.Media.MediaManager.GetMediaUrl(item);
This is what I use:
var imgField = ((Sitecore.Data.Fields.ImageField)currentItem.Fields["Icon"]);
MediaUrlOptions opt = new MediaUrlOptions();
opt.AlwaysIncludeServerUrl = true;
// Absolute Path works as well. So either use AbsolutePath or AlwaysIncludeServerUrl
opt.AbsolutePath = true;
string mediaUrl = MediaManager.GetMediaUrl(imgField.MediaItem, opt);
I'm using sitecore 6.5 with two languages installed, en (default) and fr-CA. There are items in the tree with content in both en and fr-CA.
The problem is that the French url has 'fr-CA' in it and we want that to be 'fr', for example:
http://website.com/fr/page.aspx instead of http://website.com/fr-CA/page.aspx
I tried renaming the language from 'fr-CA' to 'fr' and that fixed the url but the content still points to the old language 'fr-CA', so the item shows three languages: en, fr and fr-CA. It's not recognizing the name change.
Any suggestions are much appreciated.
Thanks,
Tarek
The problem is you have created fr-CA versions of your items which cannot be fixed by renaming the language .. you can now make a fr version but, like you are seeing, this means there are now 3 possible versions.
One suggestion is to leave the languages in Sitecore alone and alter how links are served and processed instead.
You would probably need to look at adding your own method into the httpRequestBegin pipeline in Sitecore. This would follow the LanguageResolver entry. You can then parse the RawUrl and set Sitecore.Context.Langauge' to French if the first element in it matched/fr/`.
Extremely quick & dirty example:
public class MyLanguageResolver : HttpRequestProcessor
{
public override void Process(HttpRequestArgs args)
{
string languageText = WebUtil.ExtractLanguageName(args.Context.Request.RawUrl);
if(languageText == "fr")
{
Sitecore.Context.Language = LanguageManager.GetLanguage("fr-CA");
}
}
}
You would probably also have to override the LinkProvider in the <linkManager> section of the web.config to format your URLs when they are resolved by Sitecore.
Another extremely quick & dirty example:
public class MyLinkProvider : LinkProvider
{
public override string GetItemUrl(Sitecore.Data.Items.Item item, UrlOptions options)
{
var url = base.GetItemUrl(item, options);
url = url.Replace("/fr-CA/", "/fr/");
return url;
}
}
Another way (slightly more long-winded as it will need to be executed via a script) is to copy the data from the fr-CA version to the fr version and then delete the fr-CA version of each item.
Rough helper method that encompasses what you're trying to do
private void CopyLanguage(ID id, Language sourceLanguage, Language destinationLanguage)
{
var master = Database.GetDatabase("master");
var sourceLanguageItem = master.GetItem(id, sourceLanguage);
var destinationLanguageItem = master.GetItem(id, destinationLanguage);
using (new SecurityDisabler())
{
destinationLanguageItem.Editing.BeginEdit();
//for each field in source, create in destination if it does not exist
foreach (Field sf in sourceLanguageItem.Fields)
{
if (sf.Name.Contains("_")) continue;
destinationLanguageItem.Fields[sf.Name].Value = sf.Value;
}
destinationLanguageItem.Editing.AcceptChanges();
////Remove the source language version
ItemManager.RemoveVersions(sourceLanguageItem,sourceLanguage, SecurityCheck.Disable);
}
}
Another way to update the languages on your content items is:
Export the fr-CA language to a .xml file (Using the Control Panel)
In the .xml file replace all and tags with the and
Rename fr-CA language in the master database to the fr
Import language from the .xml file
Run Clean Up Databases task (from the Control Panel)
Also you can create a sql script that will change fr-CA language with the fr for all records in the UnversionedFields and VersionedFields tables.
If you need any more information or examples please let me know. :)
I had a similar requirement to rename a language while retaining the content. I decided to migrate content from one language to another by using Unicorn:
1: Create a predicate telling Unicorn to track all of your content. In my case:
<include name="site content" database="master" path="/sitecore/content/mySite" />
Reserialize the content, writing it to disk as YML files
Using a tool that can perform a find & replace in multiple files at once, such as Notepad++, replace all instances of "Language: fr-CA" with "Language: fr" in your yml files.
Run a Unicorn Sync
You will find that all of your content is now associated with the "fr" language instead of "fr-CA".