September 30, 2016

How to setup multilingual site in SharePoint with Google Translatation

Introduction
There are multiple ways to implement multilingual sites in SharePoint, like MUI, Variation, Google Translate. Here, I will explain the basic concept of these 3 options that can be used which suites our requirements.

1. Multilingual User Interface(MUI)
This option creates a site in default language that is selected while creating a Site. For example, if the Chinese language is selected when the site was created, the site user interface will appear in Chinese. We need to add different language pack and configure site for multiple languages.
Limitations:
It only affects the site administration pages and OOTB SharePoint navigation, welcome message, column headers etc. But it doesn’t support user-created content, such as list item data, documents and web pages in libraries, custom permission levels, and custom groups. Also, it requires publishing feature, and thus requires SharePoint Server license. it won't work with SharePoint Foundation.

2. Variations
When variation is enabled, SharePoint will automatically build a variation of the site in parallel. This option creates a source variation site that is used to author content in one language, and then it will sync that content to one or more target variation sites in other languages. For example, you can author and publish content in English language for http://yoursitename.com/en, and use variation to sync content to http://yoursitename.com/fr, where it can be translated into French.
Limitations:
SharePoint creates two alternate versions of the site as you build out the structure of the source site. This option basically increases the content DB size as it creates new site collection for each variation. It can’t translate any content you build on the source site. You will need to recreate the content from the source site to variation site. It also requires publishing feature, hence can work only with SharePoint Server.

3. Google Translation
The 3rd option while creating a multilingual site is using the machine translation tool. Google Translation is free option for language translation tool for SharePoint. The SharePoint site is run through a translation engine and re-rendered in selected language. It works with SharePoint foundation, too. Here, we will see how we can convert whole SharePoint site content in preferred language.

How to implement multilingual site using Google Translate:

I have created a WSP package in SharePoint solution which contains:
1. User Control - For a dropdown control which contains a list of available languages.
2. JavaScript - To translate the content in other languages.
3. Custom master page – to add control in it, so that the translation control will be available throughout the site.


Step 1:
Create a user-control(.ascx) with dropdown list through which user can select a language to translate site content. Here, I have added only few languages, but we can add as many as needed.
e.g.
<li role="presentation"><a href="#" data-lang="Indonesian" role="menuitem" tabindex="-1">Indonesian </a> </li>


 
<div id="google_translate_element" style="display: none !important;"></div>
<div class="dropdown" style="margin: 0px; text-align: right; padding-right: 0px;">
<!-- Use CSS to replace link text with flag icons -->
<a class="dropdown-toggle" id="translatebutton" data-toggle="dropdown" aria-expanded="true"><!--<img/>--> Translate </a>
<div class="dropdown-menu dropdown-menu-right translation-links" role="menu" aria-labelledby="dropdownMenu1" id="translateblock">
<div id="translateblocknotice">Select your language </div>
<ul class="col-md-3 col-xs-6 translateblockcolumn">
<li role="presentation">
<a href="#" data-lang="English" role="menuitem" tabindex="-1"> English </a> </li>
<li role="presentation">
<a href="#" data-lang="Afrikaans" role="menuitem" tabindex="-1"> Afrikaans </a></li>
<li role="presentation">
<a href="#" data-lang="Albanian" role="menuitem" tabindex="-1"> Albanian </a> </li> <li role="presentation">
<a href="#" data-lang="Swahili" role="menuitem" tabindex="-1"> Swahili </a> </li> </ul>
</div>
</div>


<script src="https://code.jquery.com/jquery-3.1.0.min.js" integrity="sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s=" crossorigin="anonymous"></script>
<script src="http://translate.googleapis.com/translate_static/js/element/10/element_main.js" type="text/javascript"></script>
<script src="http://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit" type="text/javascript"></script>
<script type="text/javascript">
function googleTranslateElementInit() {
new google.translate.TranslateElement({
pageLanguage: 'en', layout:
google.translate.TranslateElement.InlineLayout.SIMPLE
},
'google_translate_element');
}
</script>

<script type="text/javascript">
$('.translation-links a').click(function () {
var lang = $(this).data('lang');
var $frame = $('.goog-te-menu-frame:first');
if (!$frame.size()) {
alert("Error: Could not find Google translate frame.");
return false;
}
$frame.contents().find('.goog-te-menu2-item span.text:contains(' + lang + ')').get(0).click();
return false;
});
</script>


Step 2:
Now, open master page and reference the user control we have created. After adding the user control, master page will look like:

<div class="col-lg-6 col-xs-5" id="translate">
<!--SPM:<%@ Register TagPrefix="ucTranslator" TagName="Translator" Src="~/_controltemplates/15/MyProject/Translator.ascx" %>-->
<!--CS: Start Create Snippets From Custom ASP.NET Markup Snippet-->
<!--SPM:<ucTranslator:Translator runat="server" id="Translator"/>-->
<!--CE: End Create Snippets From Custom ASP.NET Markup Snippet-->
</div>


Step 3:
Build and deploy the solution.

Results
As shown in below image, you can see Translate link on top of the page. Click on Translate link and select any language, site content will be translated in the desired language.


On clicking Translate link, it shows available languages content can be translated into.
Selecting Chinese language, content will be translated as shown below.



The limitation of this approach is, it won’t work with left to right language like Arabic. It will just convert the content in Arabic language.  "Variation" is the option if you want entire site to be translated from Right to left through.

If you have any questions you can reach out our SharePoint Consulting team here.

September 14, 2016

Enable Auditing for Exchange On-Premise/Online

Email Auditing in Exchange On-Premise/Online (Office 365)
In Exchange, we can turn on mailbox auditing to log mailbox access by mailbox owners, delegates, and administrators. By default, mailbox auditing in Exchange is not turned on.

After we enable mailbox audit logging for a mailbox, certain actions performed by administrators and delegates will be logged by default. However, to log actions performed by the mailbox owner, we have to specify which actions of owner should be audited.

Mailbox audit logs are generated for every mailbox that has mailbox auditing is enabled.
Log entries are stored in the Recoverable Items folder in the audited mailbox, in the sub-folder named "Audits".

This ensures that all audit log entries are available from a single location, regardless of which client access method was used to access the mailbox OR which server/workstation is used by an administrator to access the audit logs.

1. Can we move and save Exchange Audit logs to another location?
If you move a mailbox to another Mailbox server, the mailbox audit logs for that mailbox are also moved because they're located in the mailbox itself.

2. Can we increase duration of Exchange Audit logs storage?
By default, mailbox audit log entries are retained in the mailbox for 90 days and then deleted. You can modify this retention period by using the AuditLogAgeLimit parameter with the Set-Mailbox cmdlet.

3. Can we increase Exchange Audit logging details?
Exchange provides out of the box features for Email auditing. But for additional settings/details we can use PowerShell commands.


How to Enable Mailbox auditing in Exchange On-Premise/Online
1.     This command can be skipped for Exchange On-Premise. On your local computer, open Windows PowerShell and run the following command.
$UserCredential = Get-Credential

2.     This command can also be skipped for Exchange On-Premise. Run the following command.
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic –AllowRedirection

3.     This command can be skipped for Exchange On-Premise. Run the following command.
Import-PSSession $Session

4.     To verify that you’re connected to your Exchange Online organization, run the following command to get a list of all the mailboxes in your organization.
Get-Mailbox

5.     Enable mailbox audit logging
Get-Mailbox -ResultSize Unlimited -Filter {RecipientTypeDetails -eq "UserMailbox"} | Set-Mailbox -AuditEnabled $true

6.     Increase duration of storage of logs
Get-Mailbox -ResultSize Unlimited -Filter {RecipientTypeDetails -eq "UserMailbox"} | Set-Mailbox - AuditlogAgelimit  “number of days to increase”

Example- Get-Mailbox -ResultSize Unlimited -Filter {RecipientTypeDetails -eq "UserMailbox"} | Set-Mailbox -AuditlogAgelimit  120

You can visit TechNet Article for Exchange Online (Office 365) and TechNet Article for Exchange On-Premise for more details on PowerShell Commands for Exchange Auditing.

If you have any questions you can reach out our SharePoint Consulting team here.

September 13, 2016

Enable Auditing for SharePoint Online & SharePoint 2013 On-Premise

Auditing in SharePoint Online and SharePoint 2013 On-Premise
SharePoint Online/On-Premise has built-in audit feature that enable us to track administrative activities.

With SharePoint auditing, we can monitor site collection level administration such as permission changes, role updates, group membership changes and changes to the audit policy itself.

There are few areas of SharePoint administration which can't be audited, such as; farm administrator assignments, site collection creation and other farm level operations.

For SharePoint auditing, we have to use “Audit log reports” settings from Site Collection Settings. Both, SharePoint Online (Office 365) and SharePoint On-Premise have different options for auditing settings.

Steps to configure Auditing in SharePoint:
1. Navigate to Site Settings of Root level site.
2. Click "Audit log reports" under "Site Collection Administration" section.
3. Configure the Auditing according to the requirements.

1. Following image shows audit settings that are available in SharePoint Online (Office 365).

2. Following image shows audit settings that are available in SharePoint 2013 On-Premise.

FAQs
1. Can we increase duration of storage for SharePoint audit reports?
For SharePoint auditing, it provides report based logs that can be utilize to see overall all usage of sites, documents, lists, etc.

To see audit log, first we have to select location (SharePoint list) where we want to save our audit log report.

If we are using Office 365, then storage limit is based on our storage quota for Office 365 tenant. If we are using On-Premise version, then storage quota is based on storage capacity of our server.

Storage limit is also based on list, maximum items it can handle. We can also set document retain settings after which audit report will be deleted.

2.  Can we move and save SharePoint audit logs to another location?
Audit logs are saved to list as excel file and we can download that file to check the report. We can move this audit log files as we desire and this way we can save/move logs.

3.  Can we increase SharePoint audit log details?
We cannot change logging details for auditing, but we can use audit settings where it provides some items that can be included/removed from audit log report.

If you have any questions you can reach out our SharePoint Consulting team here.

September 8, 2016

Injecting Javascript file through SharePoint Hosted App

A requirement came across was to execute a JavaScript on all the pages of SharePoint Site. Here, option of achieving the functionality by developing custom master page was eliminated as we were dealing with a SharePoint Hosted App. It is also easy to achieve through server side but need to find solution on client side as SharePoint Hosted App has everything on client side. Finally, we found a solution to inject the JavaScript using Custom Action.

JavaScript Object Model (JSOM) allows us to programmatically register Custom Action with Host Web in a way similar to declarative approach used with Farm or Sandboxed Solution. In order to register a Custom Action using JSOM, your app requires the Full Control permission on the Site/Site Collection where you want to register it.

To achieve this, we need to perform two steps as below:
  1. Provisioning the JavaScript file from App web to Host web
  2. Registering the Custom action with the file path referring to that JavaScript file in the Host web.

1. Provisioning the JavaScript file from app web to host web:

function uploadFileToHostWebViaCSOM(serverRelativeUrl, filename, contents) {      
        var executor = new SP.RequestExecutor(window.appWebUrl);
        executor.executeAsync(
                {
                    url: window.appWebUrl + "/_api/SP.AppContextSite(@target)/web/GetFolderByServerRelativeUrl('" + serverRelativeUrl + "')/Files?@target='" + window.hostWebUrl + "'",
                    method: "GET",
                    headers: { "Accept": "application/json; odata=verbose" },
                    success: function (data) {
                        var jsonObject = JSON.parse(data.body);
                        var createInfo = new SP.FileCreationInformation();
                        createInfo.set_content(new SP.Base64EncodedByteArray());
                        for (var i = 0; i < contents.length; i++) {
                            createInfo.get_content().append(contents.charCodeAt(i));
                        }
                       createInfo.set_url(filename);
                       createInfo.set_overwrite(true);
                       var files = hostWebContext.get_web().getFolderByServerRelativeUrl(serverRelativeUrl).get_files();
                       var isexist = false;
                        jsonObject.d.results.forEach(function (item, index) {
                            if (item.Name == filename)
                                isexist = true;
                        });
                        if (isexist)
                            files.getByUrl(filename).checkOut();
                        var file = files.add(createInfo);
                        file.checkIn('Add-in deployment.');
                        file.publish('Add-in deployment.');

                        appWebContext.load(file);
                        appWebContext.executeQueryAsync(success, function (sender, args) {
                            alert(args.get_message());
                        });
                    },
                    error: function (data, errorCode, errorMessage) {
                        console.log("error");
                    }
                });
    };


Here, we are first fetching the file from app web and checking that whether it exists in host web or not. If the file exists then we will update the existing file, check in and publish it. If the file does not exist then we just add the file, check in and publish it.

2. Registering the custom action with the file path:

var context = web.get_context();
var webs = web.get_webs();
var actions = web.get_userCustomActions();
context.load(actions);
context.load(webs, 'Include(Title,Webs)');
context.executeQueryAsync(function () {

  var newAction = actions.add();
  // the 'description' is what we'll use to uniquely identify our custom action
  newAction.set_description(actionDescription);
  newAction.set_location('ScriptLink');
  newAction.set_scriptBlock(getScripts(window.hostWebUrl + '/Style Library/EasyNav/Scripts/tinysort.min.js'));
  newAction.set_sequence(1004);
  newAction.update();

  context.executeQueryAsync(function () { }, fail);
}, fail);

The above code adds a custom action on a web object in Host web. Wherein,
set_location specifies it is a script registration action,
set_scriptBlock indicates the JavaScript file's path in host web,
set_sequence specifies the sequence in which the files are to be loaded if there is more than one.

Once above code will be executed through custom action, we can see all JavaScript files loaded on all the pages of the SharePoint Site.

If you have any questions you can reach out our SharePoint Consulting team here.

Access Web App – Related Items Control - Parent/Child data in a Single View



Introduction

Today, I'll guide you through in detail how we can display and manage related data from 2 different tables, having parent/child relationship in a single view in SharePoint 2013 - Access Web app.
 
First, Create two tables: "Country" and "State". Now, if we want to view all States of the specific Country in Country Table View. That’s where the Related Item Control comes into picture!! Here, If you navigate to a record in Country table, you’ll see all States of that Country. You can also add other new States for that country from the same view.



Here are the steps to achieve the functionality:
  • Create "Country" and "State" tables with required fields in MS Access 2013.
  • For Country reference, add a lookup column which points to country name field in Country table, here it is ‘CID’.


  • Now, you can add data in Country and State tables and publish the app in SharePoint 2013. You can also insert same data from SharePoint List.

  • Country list view will look as below after adding data.
  • Add another control on list view called “Related Items Controls”, to show related state details on Country list view.
  • Configure it to display related state data as shown below.




  • Save view and launch the app.
  • Here, we can add new state details and/or also edit existing state data from this view.

If you have any questions you can reach out our SharePoint Consulting team here.